3

I am new to C++ and i am trying to write a LinkedList class with a LinkedListIterator utility class as below. (i have listed only the code parts that are relevant to the question). I have created the LinkedListIterator constructor as private.

Now, when I have these two lines in main(),

 LinkedListIterator iter = list->begin(); <<== No compilation error LinkedListIterator iter2; <<==== compilation error. 

i get the compilation error for the 2nd line, which is expected as the default constructor is private. However, I dont understand why there is no compilation error for the first line ? Why ? what is getting called for the first line of the code ? Private constructor or Copy constructor or assignment operator ?

Code

class LinkedListIterator { public: bool operator== (LinkedListIterator i) const; bool operator!= (LinkedListIterator i) const; void operator++ (); // Go to the next element int& operator* (); // Access the current element inline Node* hasnext(); inline Node* next(); private: LinkedListIterator(Node* p); <<==== Private constructor LinkedListIterator(); <<==== Private constructor Node* p_; friend class LinkedList;//LinkedList can construct a LinkedListIterator }; .... inline LinkedListIterator::LinkedListIterator(Node* p) : p_(p) { } inline LinkedListIterator::LinkedListIterator() { } inline LinkedListIterator LinkedList::begin() { return first_; } inline LinkedListIterator LinkedList::end() { return NULL; } ....... class LinkedList { public: void append(int elem); // Adds elem after the end void printList(); LinkedList() { first_ = NULL; } LinkedListIterator begin(); LinkedListIterator end(); LinkedListIterator erase(int elem); private: Node* first_; }; main() { LinkedList *list = new LinkedList(); list->append(1); list->append(2); list->append(3); LinkedListIterator iter = list->begin(); <<== No compilation error LinkedListIterator iter2; <<==== compilation error. } 

2 Answers 2

8

LinkedListIterator iter = <some other LinkedListIterator> is called copy initialization and calls a "hidden" constructor: the copy constructor (C++03) resp. move constructor (if present, and if the initializer is a temporary, in C++11). These two constructors are not provided in your code, yet they exist: They are generated by the compiler, and they are generated as public. Therefore they are accessible from outside the class and you do not get a compiler error.

Bartek mentions copy elision in his answer, so I'll add my remark for clarity: The copy/move ctor must be accessible (in this case: public) for copy initialization, regardless of wether copy elision takes place or not, i.e. even if it does not get called.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks Arne Mertz for the quick response and detailed explanation. Let me do some reading on the new terms that you introduced :)
@user2896235 note that "hidden" is no official term, while "copy initialization" is.
3

There's no compilation error because the constructor is called from (i.e. "the object is created in") the LinkedList class (in particular from its begin() member function), which is a friend. No one else can instantiate that class, so the second line fails.


Specifically, looking at begin():

inline LinkedListIterator LinkedList::begin() { return first_; } 

it's (with regard to access) equivalent to:

 return LinkedListIterator(first_); 

which calls private LinkedListIterator::LinkedListIterator(Node* p).

Then, copy ellision could be performed, or a default copy (or move) constructor, which is public by default, could be called.

2 Comments

note that even if copy elision occurs, the copy/move constructor has to be public for this to work.
@ArneMertz good point. Your answer is "more correct" in general, anyway.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.