-1

I'm new to c++ learning to implement linked lists, i don't understand why i when i don't call by reference in the arguments of the function insertAtfront the output becomes wrong? and why does the argument have to be const reference?

#include <iostream>

template <typename T>
class List {
public:
  const T & operator[](unsigned int data);
  void insertAtFront(const T & data);//&
private:
  class ListNode {
  public:
    const T & data;
    ListNode * next;
    ListNode(const T & data_): data(data_), next(nullptr){} //&
  };
    ListNode * head_=nullptr;
};

template <typename T>
const T & List<T>::operator[](unsigned int index){
  ListNode * through=head_;
  while(index>0  && through->next!=nullptr){
    through = through->next;
    index--;
  }
  return through->data;
}
template <typename T>
void List<T>::insertAtFront(const T & data){ //&
  ListNode * Ptr=new ListNode(data);

  Ptr->next=head_;
  head_=Ptr;
}
int main(){
  List<int> L;
  L.insertAtFront(2);
  L.insertAtFront(55);
  std::cout<<L[0]<<std::endl;
  std::cout<<L[1]<<std::endl;
}
cigien
  • 57,834
  • 11
  • 73
  • 112
  • It doesn't have to be `const` but if it is it means you're promising not to edit it. It can be a reference to a pointer, a reference to an integer, a reference to anything really. – tadman Aug 18 '20 at 02:30
  • 2
    You shouldn't really be storing a reference in your `ListNode`; I think that is the underlying issue. – Ken Y-N Aug 18 '20 at 02:34
  • 2
    Can you post the "wrong" version as well? Or it's just remove the `&` from `insertAtfront`? – Louis Go Aug 18 '20 at 02:36
  • 1
    Your `ListNode` should not have `const T & data` because it might take a data from rvalue. Use ``const T data` – Louis Go Aug 18 '20 at 02:42
  • @LouisGo the wrong version is whenever i remove the & or the const – Loay Salem Aug 19 '20 at 00:22
  • @tadman whenever i remove the const it gives wrong data it always read what's stored in the list as zero – Loay Salem Aug 19 '20 at 00:23

1 Answers1

0

You list holds the reference of input data while not knowing when the reference would be cleaned up.

I tuned it into following code: Or try it on https://godbolt.org/z/7GG5rW

#include <iostream>

template <typename T>
class List {
public:
  const T & operator[](unsigned int data);
  void insertAtFront(const T data); // Remove &
private:
  class ListNode {
  public:
    const T data;  // Remove &
    ListNode * next;
    ListNode(const T & data_): data(data_), next(nullptr){} // Remove &
  };
    ListNode * head_=nullptr;
};

template <typename T>
const T & List<T>::operator[](unsigned int index){
  ListNode * through=head_;
  while(index>0  && through->next!=nullptr){
    through = through->next;
    index--;
  }
  return through->data;
}
template <typename T>
void List<T>::insertAtFront(const T & data){ //&
  ListNode * Ptr=new ListNode(data);

  Ptr->next=head_;
  head_=Ptr;
}
int main(){
  List<int> L;
  L.insertAtFront(2);
  L.insertAtFront(55);
  std::cout<<L[0]<<std::endl;
  std::cout<<L[1]<<std::endl;
}

For optimization, you may use std::move or perfect forwarding to increase performance.

Louis Go
  • 2,213
  • 2
  • 16
  • 29