2

I have done some reading starting on the Rule of three and this has given me some exposure to memory management when writing C++ and it is challenging coming from a Java background.

I'm just writing some toy programs to begin with and just wanting to construct a basic linked list.

I have my Node:

class Node
{
   public:
      std::string des;
      int val;
      Node *nxt;
      Node();
      Node(std::string d, int v) : des(d), val(v);
      ~Node();
   private:    

}

And my Linked List:

class LinkedList
{
   public:
      Node *hd;
      Node *tl;
      LinkedList() : hd=nullptr, tl=nullptr;
      void Append(const Node &nod)
      {
         hd=nod; 
      }
      ~LinkedList();
   private:

}

I wanted to write the code like this going from what I have learned so far.

int main(void)
{
   
   std::cout << "Create some objects on the stack." << std::endl;
   LinkedList m_ls();
   Node m_nod1("first node", 30);
   Node m_nod1("second node", 36);
   Node m_nod1("third node", 42);
   
   m_ls.Append(m_nod1);
   m_ls.Append(m_nod2);
   m_ls.Append(m_nod3);

}

I am getting an obvious compiler warning because my assignment of this->hd=nod but it is not obvious to me how I'm to write this properly. Will casting between types and a copy-constructor solve this? Appreciate the help.

11
  • 1
    Your classes both violate the rule-of-three that you mention, but that's completely unrelated to what you are asking about. A reference is not a pointer. You get a pointer to an object from an expression resulting in that object with &. That should be explained in any introduction to C++ (or C for that matter). This has nothing to do with the copy constructor or casting. However, even with that, passing a pointer/reference to a Node to the constructor is a fundamentally flawed approach because the List itself should own the Node, so it should be creating it itself as well. Commented Nov 21, 2023 at 18:52
  • If you are not doing this already: It is basically impossible to properly learn C++ without starting from the basics in a structured way. It is very unforgiving for not following rules that are not enforced by any warning or error. You need to work through a good book or course. See for example stackoverflow.com/questions/388242/…. (Correction for comment above: I meant the Append function instead of "constructor".) Commented Nov 21, 2023 at 18:55
  • @user17732522 Did you mean creating a linkedlist with an initial source Node? I guess it would make sense if you don't intend to alter it. Commented Nov 21, 2023 at 19:02
  • Recommendation: keep the Node class as simple as possible. Give it just enough smarts to hold data and know where the next node its Don't give it a destructor. Leave the management of the nodes completely up to the LinkedList and make all of the data observe the Rule of Three. Do not expose the Node class to the user. Make it a private member of LinkedList. If the user can add and remove Nodes they create or interact with them, you're allowing the user to shoot themselves in the foot by mixing automatic and dynamic storage or damage the Node and , by extension, the LinkedList. Commented Nov 21, 2023 at 19:03
  • 1
    @ThomasMatthews At least in the C++ standard itself, there is no such 32-character restriction. The standard recommends that compilers support at least 1024 for internal/external identifier names, see Annex B (although this is not mandatory). For example, MSVC supports 2048 characters, see Identifiers (C++). Commented Nov 21, 2023 at 19:55

1 Answer 1

0

To answer your specific question - to fix the compiler error, you would need to drop the const from your nod parameter, and then use the address-of operator& to get the memory address of the passed Node object when assigning it to the hd pointer, eg:

void Append(Node &nod)
{
   hd = &nod; 
}

However, this is not the correct way to write a linked list class (at least in this example). You should instead not let the user pass in Node objects at all, they should only pass in the data they want to add to the list, let the LinkedList class handle the Node objects internally as needed.

For example:

class Node
{
   public:
      std::string des;
      int val;
      Node *nxt = nullptr;
      Node(std::string d, int v) : des(d), val(v) {}
};

class LinkedList
{
   public:
      LinkedList() = default;

      ~LinkedList()
      {
         Node *nd = hd, *nxt;
         while (nd)
         {
            nxt = nd->nxt;
            delete nd;
            nd = nxt;
         }
      }

      void Append(std::string des, int val)
      {
         Node *n = new Node(des, val);
         if (!hd) hd = n;
         if (tl) tl->next = n;
         tl = n;
      }

      // implement these later during your Rule-of-3/5 studies...
      LinkedList(const LinkedList&) = delete;
      LinkedList(LinkedList&&) = delete;
      LinkedList& operator=(const LinkedList&) = delete;
      LinkedList& operator=(LinkedList&&) = delete;

   private:
      Node *hd = nullptr;
      Node *tl = nullptr;
};

int main()
{
   std::cout << "Create some objects in the list." << std::endl;

   LinkedList m_ls;
   m_ls.Append("first node", 30);
   m_ls.Append("second node", 36);
   m_ls.Append("third node", 42);
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.