449,412 Members | 993 Online
Need help? Post your question and get tips & solutions from a community of 449,412 IT Pros & Developers. It's quick & easy.

# Confused by the constructor and cop-constructor.

 P: n/a The fragment code: #include using namespace std; class Integer { int i; public: Integer() : i(0) {}; Integer(int I) : i(I) {}; Integer(Integer & other) : i(other.i) {} // line 10 Integer & operator=(Integer &other) { i = other.i; return (* this); } Integer & operator=(int a) { i = a; return (* this); } friend ostream& operator<<(ostream &os, Integer &I) { os << I.i; return os; } }; int main() { int a = 5; Integer Int1 = a; // line 27; error happens here. Integer Int2 = Int1; // line 28; cout << Int1 <<", " << Int2 << endl; Int1 = 5; // line 31 cout << Int1 <<", " << Int2 << endl; Int2 = Int1; // line 33 cout << Int1 <<", " << Int2 << endl; } case 1: If the line 10 is there, compiling aborts at line 27. g++.exe "Integer.cpp" -o Integer.exe" -g3 -I"d:\Dev-Cpp\include\c++" -I"d:\Dev-Cpp\include\c++\mi ngw32" -I"d:\Dev-Cpp\include\c++\backward" -I"d:\Dev-Cpp\include" -L"d:\ Dev-Cpp\lib" Integer.cpp: In function `int main()': Integer.cpp:27: no matching function for call to `Integer::Integer(Integer)' Integer.cpp:10: candidates are: Integer::Integer(Integer&) Integer.cpp:9: Integer::Integer(int) Integer.cpp:27: initializing temporary from result of ` case 2: If the line 10 is delete, there is no error at line 27 when compiling. Could someone explain this for me? What does line 27 do in detail? Invoke Integer::Integer(int I) directly? or Create a temporary Integer object from the variable 'a' and use copy-constructor to create Int1 from this termporary object? Could someone explain more in details on line 27, 28, 31 and 33? What's the difference among them? Thanks a lot. Best Regards, Xiangliang Meng Jul 22 '05 #1
9 Replies

 P: n/a I've fiddled with the code a little. The following compiles: #include using namespace std; class Integer { private: int i; public: Integer() : i(0) {;} Integer(int I) : i(I) {;} //Instead of the two above you could have: //Integer(int I = 0) : i(I) {;} Integer(Integer& other) : i(other.i) {;} // line 10 Integer& operator=(Integer& other) { i = other.i; return (* this); } Integer& operator=(int a) { i = a; return (* this); } friend ostream& operator<<(ostream &os, Integer &I) { os << I.i; return os; } }; int main() { int monkey = 72; Integer Int1(monkey); //THE MAGICAL LINE Integer Int2 = Int1; cout << Int1 <<", " << Int2 << endl; Int1 = 5; cout << Int1 <<", " << Int2 << endl; Int2 = Int1; cout << Int1 <<", " << Int2 << endl; } I am at a loss to why, with THE MAGICAL LINE above: Integer Int1(monkey); will compile, while: Integer Int1 = monkey; won't!! Is this a compiler bug, because both statements should be EXACTLY THE SAME? -JKop Jul 22 '05 #2

 P: n/a Xiangliang Meng wrote: The fragment code: #include using namespace std; class Integer { int i; public: Integer() : i(0) {}; Integer(int I) : i(I) {}; Integer(Integer & other) : i(other.i) {} // line 10 Integer & operator=(Integer &other) { i = other.i; return (* this); } Integer & operator=(int a) { i = a; return (* this); } friend ostream& operator<<(ostream &os, Integer &I) { os << I.i; return os; } }; int main() { int a = 5; Integer Int1 = a; // line 27; error happens here. Integer Int2 = Int1; // line 28; cout << Int1 <<", " << Int2 << endl; Int1 = 5; // line 31 cout << Int1 <<", " << Int2 << endl; Int2 = Int1; // line 33 cout << Int1 <<", " << Int2 << endl; } case 1: If the line 10 is there, compiling aborts at line 27. g++.exe "Integer.cpp" -o Integer.exe" -g3 -I"d:\Dev-Cpp\include\c++" -I"d:\Dev-Cpp\include\c++\mi ngw32" -I"d:\Dev-Cpp\include\c++\backward" -I"d:\Dev-Cpp\include" -L"d:\ Dev-Cpp\lib" Integer.cpp: In function `int main()': Integer.cpp:27: no matching function for call to `Integer::Integer(Integer)' Integer.cpp:10: candidates are: Integer::Integer(Integer&) Integer.cpp:9: Integer::Integer(int) Integer.cpp:27: initializing temporary from result of ` case 2: If the line 10 is delete, there is no error at line 27 when compiling. Could someone explain this for me? Integer Int1 = a; // line 27; error happens here. Here a temporary Integer object is created from a. This temporary is then feed into the copy constructor to create Int1. The signature of your copy constructor is: Integer(Integer & other) : i(other.i) {} // line 10 But a temporary cannot be bound to a reference which is not const! Thus the error. If you don't write the copy constructor yourself, the compiler generates one. But the compiler generated has the signature Integer( const Integer & other) : i(other.i) {} // line 10 See the difference? This difference is, why the compiler generated one works, while yours doesn't. What does line 27 do in detail? Invoke Integer::Integer(int I) directly? or Create a temporary Integer object from the variable 'a' and use copy-constructor to create Int1 from this termporary object? The later one. Could someone explain more in details on line 27, 28, 31 and 33? What's the difference among them? 27: Integer Int1 = a; object gets created -> constructor is used, Thus 'a' first has to be transformed into an Integer object, use the ctor which takes an int for that. 28: Integer Int2 = Int1; object gets created -> constructor is used Since Int1 is already an Integer object, use the copy constructor for Int2 31: Int1 = 5; This is an assignment. Thus an opertor= is used. First try to find something that allows an int to be assigned directly to an Integer -> Integer & operator=(int a) is found and used 33: Int2 = Int1; This is an assignment. Thus an operator= is used. Find an operator= which can take an Integer object -> Integer & operator=(Integer &other) is found and used. -- Karl Heinz Buchegger kb******@gascad.at Jul 22 '05 #3

 P: n/a Xiangliang Meng wrote: The fragment code: #include using namespace std; class Integer { int i; public: Integer() : i(0) {}; Integer(int I) : i(I) {}; Integer(Integer & other) : i(other.i) {} // line 10 Integer & operator=(Integer &other) { i = other.i; return (* this); } Integer & operator=(int a) { i = a; return (* this); } friend ostream& operator<<(ostream &os, Integer &I) { os << I.i; return os; } }; int main() { int a = 5; Integer Int1 = a; // line 27; error happens here. Integer Int2 = Int1; // line 28; cout << Int1 <<", " << Int2 << endl; Int1 = 5; // line 31 cout << Int1 <<", " << Int2 << endl; Int2 = Int1; // line 33 cout << Int1 <<", " << Int2 << endl; } case 1: If the line 10 is there, compiling aborts at line 27. g++.exe "Integer.cpp" -o Integer.exe" -g3 -I"d:\Dev-Cpp\include\c++" -I"d:\Dev-Cpp\include\c++\mi ngw32" -I"d:\Dev-Cpp\include\c++\backward" -I"d:\Dev-Cpp\include" -L"d:\ Dev-Cpp\lib" Integer.cpp: In function `int main()': Integer.cpp:27: no matching function for call to `Integer::Integer(Integer)' Integer.cpp:10: candidates are: Integer::Integer(Integer&) Integer.cpp:9: Integer::Integer(int) Integer.cpp:27: initializing temporary from result of ` case 2: If the line 10 is delete, there is no error at line 27 when compiling. Could someone explain this for me? What does line 27 do in detail? Invoke Integer::Integer(int I) directly? or Create a temporary Integer object from the variable 'a' and use copy-constructor to create Int1 from this termporary object? Could someone explain more in details on line 27, 28, 31 and 33? What's the difference among them? Thanks a lot. Best Regards, Xiangliang Meng This doesn't particularly answer all your questions, but you can get rid of the compiler error if you change line 10 to: Integer(const Integer & other) : i(other.i) {} I'll try later to look it up and see exactly why the error you are getting occurs, if nobody beats me to it. Alan Jul 22 '05 #4

 P: n/a JKop wrote: I am at a loss to why, with THE MAGICAL LINE above: Integer Int1(monkey); will compile, while: Integer Int1 = monkey; won't!! Is this a compiler bug, because both statements should be EXACTLY THE SAME? No they are not. In Integer Int1 = monkey; first a temporary Integer object is created from monkey, which is then used with the copy constructor to initialize Int1 while in Integer Int1(monkey); The constructor taking an int is used. Integer Int1 = monkey; is equivalent to Integer Int1 ( Integer( monkey ) ); Don't worry about the temporary object. The compiler is allowed to optimize it away in all circumstances (even if the copy constructor has side effects) and will normally do so. -- Karl Heinz Buchegger kb******@gascad.at Jul 22 '05 #5

 P: n/a Hi, all The behavior is different from our imagination. This is very surprising for me too. Although I was not sure several hours ago, I thought there is a temporary object will be created in this scenario. int a = 5; Integer Int1 = a; It, however, is the same as Integer Int1(a). I do not know whether the compile does optimize to some extent in this line. If so, the compile might replace creating temporay object with invoking the constructor directly. The output result is: Integer::Integer(int I) //**** here is it. This means no temporary object is created for invoking copy-constructor. Integer::Integer(const Integer & other) 5.10, 5.10 Integer::operator=(int a) 5.10, 5.10 Integer::operator=(Integer &other) 5.10, 5.10 The new cold with a little change: #include using namespace std; class Integer { int i; int j; // I add this new data member and hope it could prevent the compile do optimize in that procedure. public: Integer() : i(0), j(0) { cout << "Integer::Integer()" << endl; } Integer(int I) : i(I), j(I*2) { cout << "Integer::Integer(int I)" << endl; } Integer(const Integer & other) : i(other.i), j(other.j) { cout << "Integer::Integer(const Integer & other)" << endl; } Integer & operator=(Integer &other) { i = other.i; j = other.j; cout << "Integer::operator=(Integer &other)" << endl; return (* this); } Integer & operator=(int a) { i = a; j = a * 2; cout << "Integer::operator=(int a)" << endl; return (* this); } friend ostream& operator<<(ostream &os, Integer &I) { os << I.i << "." << I.j; return os; } }; int main() { int a = 5; Integer Int1(a); Integer Int2 = Int1; cout << Int1 <<", " << Int2 << endl; Int1 = 5; cout << Int1 <<", " << Int2 << endl; Int2 = Int1; cout << Int1 <<", " << Int2 << endl; } "Xiangliang Meng" wrote in message news:cb**********@zcars0v6.ca.nortel.com... The fragment code: #include using namespace std; class Integer { int i; public: Integer() : i(0) {}; Integer(int I) : i(I) {}; Integer(Integer & other) : i(other.i) {} // line 10 Integer & operator=(Integer &other) { i = other.i; return (* this); } Integer & operator=(int a) { i = a; return (* this); } friend ostream& operator<<(ostream &os, Integer &I) { os << I.i; return os; } }; int main() { int a = 5; Integer Int1 = a; // line 27; error happens here. Integer Int2 = Int1; // line 28; cout << Int1 <<", " << Int2 << endl; Int1 = 5; // line 31 cout << Int1 <<", " << Int2 << endl; Int2 = Int1; // line 33 cout << Int1 <<", " << Int2 << endl; } case 1: If the line 10 is there, compiling aborts at line 27. g++.exe "Integer.cpp" -o nteger.exe" -g3 -I"d:\Dev-Cpp\include\c++" -I"d:\Dev-Cpp\include\c++\mi w32" -I"d:\Dev-Cpp\include\c++\backward" -I"d:\Dev-Cpp\include" -L"d:\ Dev-Cpp\lib" Integer.cpp: In function `int main()': Integer.cpp:27: no matching function for call to `Integer::Integer(Integer)' Integer.cpp:10: candidates are: Integer::Integer(Integer&) Integer.cpp:9: Integer::Integer(int) Integer.cpp:27: initializing temporary from result of ` case 2: If the line 10 is delete, there is no error at line 27 when compiling. Could someone explain this for me? What does line 27 do in detail? Invoke Integer::Integer(int I) directly? or Create a temporary Integer object from the variable 'a' and use copy-constructor to create Int1 from this termporary object? Could someone explain more in details on line 27, 28, 31 and 33? What's the difference among them? Thanks a lot. Best Regards, Xiangliang Meng Best Regards, Xiangliang Meng Jul 22 '05 #6

 P: n/a Xiangliang Meng wrote: Hi, all The behavior is different from our imagination. This is very surprising for me too. Although I was not sure several hours ago, I thought there is a temporary object will be created in this scenario. int a = 5; Integer Int1 = a; It is. At least conceptually It, however, is the same as Integer Int1(a). Its' not the same An equivalent formulation would be Integer Int1 ( Integer( a ) ); I do not know whether the compile does optimize to some extent in this line. It surely does. This is the only (AFAIK) explicite optimization that is mentioned in the standards document. If so, the compile might replace creating temporay object with invoking the constructor directly. Yep. The output result is: Integer::Integer(int I) //**** here is it. This means no temporary object is created for invoking copy-constructor. This does not follow. What you see here is the constructor which is called to construct the temporary. Remember above? Integer Int1( Integer( a ) ); The temporary is constructed by using the constructor which takes an int. But then magic happens. The compiler aranges such that the temporary is constructed at the same place as Int1, effectively making it look like the temporary and the copy constructor are unneccessary. But you can try the following. Make the copy constructor unaccessible for the compiler. You then will find that Integer Int1 = a; will no longer compile, due to lack of copy constructor. -- Karl Heinz Buchegger kb******@gascad.at Jul 22 '05 #7

 P: n/a Xiangliang Meng wrote: The fragment code: #include using namespace std; class Integer { int i; public: Integer() : i(0) {}; Integer(int I) : i(I) {}; Integer(Integer & other) : i(other.i) {} // line 10 Integer & operator=(Integer &other) { i = other.i; return (* this); } Integer & operator=(int a) { i = a; return (* this); } friend ostream& operator<<(ostream &os, Integer &I) { os << I.i; return os; } }; int main() { int a = 5; Integer Int1 = a; // line 27; error happens here. Integer Int2 = Int1; // line 28; cout << Int1 <<", " << Int2 << endl; Int1 = 5; // line 31 cout << Int1 <<", " << Int2 << endl; Int2 = Int1; // line 33 cout << Int1 <<", " << Int2 << endl; } case 1: If the line 10 is there, compiling aborts at line 27. g++.exe "Integer.cpp" -o Integer.exe" -g3 -I"d:\Dev-Cpp\include\c++" -I"d:\Dev-Cpp\include\c++\mi ngw32" -I"d:\Dev-Cpp\include\c++\backward" -I"d:\Dev-Cpp\include" -L"d:\ Dev-Cpp\lib" Integer.cpp: In function `int main()': Integer.cpp:27: no matching function for call to `Integer::Integer(Integer)' Integer.cpp:10: candidates are: Integer::Integer(Integer&) Integer.cpp:9: Integer::Integer(int) Integer.cpp:27: initializing temporary from result of ` case 2: If the line 10 is delete, there is no error at line 27 when compiling. Could someone explain this for me? What does line 27 do in detail? Invoke Integer::Integer(int I) directly? or Create a temporary Integer object from the variable 'a' and use copy-constructor to create Int1 from this termporary object? Could someone explain more in details on line 27, 28, 31 and 33? What's the difference among them? Line 27 is really Integer Int1 = Integer(a); which involves 2 constructors: one parameterized with 'int' and one copy constructor. However, your copy constructor expects a reference to non- const Integer. The first (parameterized) constructor here creates a temporary object, and the call to the copy constructor cannot be made because a non-const reference cannot be bound to a temporary. Line 28 is really Integer Int2(Int1); which is a copy constructor, but now 'Int1' is not a temporary, but a real object, and a non-const reference is bound to it without a problem. Line 31 is a call to the parameterized assignment operator: Int1.Integer::operator=(5); You provided it, its argument is 'int', everything is fine. Line 33 is a call to the copy assignment operator (provided to you by the compiler, since you haven't defined it yourself): Int2.Integer::operator=(Int1); The compiler-provided assignment operator has the signature Integer& operator=(Integer const&); The const reference is bound to the object (Int1) without a problem. HTH Victor Jul 22 '05 #8

 P: n/a Xiangliang Meng wrote: The behavior is different from our imagination. This is very surprising for me too. Although I was not sure several hours ago, I thought there is a temporary object will be created in this scenario. int a = 5; Integer Int1 = a; It, however, is the same as Integer Int1(a). I do not know whether the compile does optimize to some extent in this line. If so, the compile might replace creating temporay object with invoking the constructor directly. The compiler is allowed to optimise the call to the copy constructor away, however, it still has to check whether such call could be made if optimization doesn't take place. In your case, such call cannot be made, that's what the compiler complains about. It has nothing to do with imagination. It has everything to do with the language Standard. Victor Jul 22 '05 #9

 P: n/a "Karl Heinz Buchegger" wrote in message news:40***************@gascad.at... [SNIP] Integer Int1 ( Integer( a ) ); I do not know whether the compile does optimize to some extent in this line. It surely does. This is the only (AFAIK) explicite optimization that is mentioned in the standards document. [SNIP] There is another explicit optimization that is allowed by the standard, which might be treated by the compiler rather similarly to this situation. For example class CMyObj { .... }; CMyObj Function() { CMyObj LocalObj; return LocalObj; // creates a copy or not? } CMyObj Obj = Function(); Here LocalObj might not be copied returning from the function, but the implementation is allowed to create LocalObj directly into Obj. This is mentioned in the standard somehwere in the section about copying class objects. Cheers Chris Jul 22 '05 #10

### This discussion thread is closed

Replies have been disabled for this discussion.