|
|
|
#1 |
|
Messages: n/a
Hébergeur: |
Hi,
I stuck into this problem that I can't figure it out. Here is the class definition: class ctest { public: ctest(void) { cout << "ctest default constor" << endl; }; ctest(ctest& c) { cout <<"ctest copy constr" << endl; }; ctest(int a) { cout <<"ctest int constor" <<endl; }; ctest& operator= (ctest& a) { cout << "ctest copy assignment" << endl; return *this; }; operator int() { cout << "call operator int()" <<endl; return 20; } }; int main(void) { ctest cc = ctest(); } And it outputs as following: ctest default constor call operator int() ctest int constor I wonder why it will invoke "operator int()" and call "constructor with int as argument". Thanks Brad |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
On 1 jul, 00:16, "hill....@gmail.com" <hill....@gmail.com> wrote:
> Hi, > > I stuck into this problem that I can't figure it out. > Here is the class definition: > > class ctest { > public: > ctest(void) { cout << "ctest default constor" << endl; }; > ctest(ctest& c) { cout <<"ctest copy constr" << endl; }; > ctest(int a) { cout <<"ctest int constor" <<endl; }; > > ctest& operator= (ctest& a) { cout << "ctest copy assignment" << > endl; return *this; }; > operator int() { cout << "call operator int()" <<endl; return 20; } > > }; > > int main(void) > { > ctest cc = ctest(); > > } > > And it outputs as following: > ctest default constor > call operator int() > ctest int constor > > I wonder why it will invoke "operator int()" and call "constructor > with int as argument". > > Thanks > Brad I wonder where is the return( 0 ); statement. |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
> > ctest(ctest& c) { cout <<"ctest copy constr" << endl; };
You've forgot the const: ctest(const ctest& c) { cout <<"ctest copy constr" << endl; }; > > ctest& operator= (ctest& a) { cout << "ctest copy assignment" << Also up here ctest& operator= (const ctest& a) { cout << "ctest copy assignment" << and here > > operator int() { cout << "call operator int()" <<endl; return 20; } operator int()const { cout << "call operator int()" <<endl; return 20; } I think it's a good question why the compiler thinks that a non const reference should be a int.. All I did is gave you the practical solution, not the teorical. > > Brad > > I wonder where is the > > return( 0 ); > > statement. That's not necesary, it's not an error, but it's a good practice not to forget all the pieces of a program ![]() Darío |
|
|
|
#4 |
|
Messages: n/a
Hébergeur: |
On 1 jul, 00:24, Elias Salomão Helou Neto <eshn...@gmail.com> wrote:
> On 1 jul, 00:16, "hill....@gmail.com" <hill....@gmail.com> wrote: > > > > > Hi, > > > I stuck into this problem that I can't figure it out. > > Here is the class definition: > > > class ctest { > > public: > > ctest(void) { cout << "ctest default constor" << endl; }; > > ctest(ctest& c) { cout <<"ctest copy constr" << endl; }; > > ctest(int a) { cout <<"ctest int constor" <<endl; }; > > > ctest& operator= (ctest& a) { cout << "ctest copy assignment" << > > endl; return *this; }; > > operator int() { cout << "call operator int()" <<endl; return 20; } > > > }; > > > int main(void) > > { > > ctest cc = ctest(); > > > } > > > And it outputs as following: > > ctest default constor > > call operator int() > > ctest int constor > > > I wonder why it will invoke "operator int()" and call "constructor > > with int as argument". > > > Thanks > > Brad > > I wonder where is the > > return( 0 ); > > statement. Well, it does not quite solve the problem. In fact, the issue here is const-correctness, because ctest() must be used as const, but ctest has ctest& or int as arguments, being the second the only possible the compiler tryes to find a conversion. The following does not compile: #include <iostream> class ctest { public: ctest(void) { std::cout << "ctest default constor" << std::endl; }; ctest(ctest& c) { std::cout <<"ctest copy constr" << std::endl; }; //ctest(int a) { std::cout <<"ctest int constor" << std::endl; }; ctest& operator= (ctest& a) { std::cout << "ctest copy assignment" << std::endl; return *this; }; //operator int() { std::cout << "call operator int()" << std::endl; return 20; } }; int main(void) { ctest cc = ctest(); return( 0 ); } but the following does: #include <iostream> class ctest { public: ctest(void) { std::cout << "ctest default constor" << std::endl; }; ctest(const ctest& c) { std::cout <<"ctest copy constr" << std::endl; }; ctest(int a) { std::cout <<"ctest int constor" << std::endl; }; ctest& operator= (ctest& a) { std::cout << "ctest copy assignment" << std::endl; return *this; }; operator int() { std::cout << "call operator int()" << std::endl; return 20; } }; int main(void) { ctest cc = ctest(); return( 0 ); } and prints ctest default constor only once, because of optimization, I guess. |
|
|
|
#5 |
|
Messages: n/a
Hébergeur: |
On Jul 1, 11:49 am, Elias Salomão Helou Neto <eshn...@gmail.com>
wrote: > On 1 jul, 00:24, Elias Salomão Helou Neto <eshn...@gmail.com> wrote: > > > > > On 1 jul, 00:16, "hill....@gmail.com" <hill....@gmail.com> wrote: > > > > Hi, > > > > I stuck into this problem that I can't figure it out. > > > Here is the class definition: > > > > class ctest { > > > public: > > > ctest(void) { cout << "ctest default constor" << endl;}; > > > ctest(ctest& c) { cout <<"ctest copy constr" << endl; }; > > > ctest(int a) { cout <<"ctest int constor" <<endl; }; > > > > ctest& operator= (ctest& a) { cout << "ctest copy assignment" << > > > endl; return *this; }; > > > operator int() { cout << "call operator int()" <<endl;return 20; } > > > > }; > > > > int main(void) > > > { > > > ctest cc = ctest(); > > > > } > > > > And it outputs as following: > > > ctest default constor > > > call operator int() > > > ctest int constor > > > > I wonder why it will invoke "operator int()" and call "constructor > > > with int as argument". > > > > Thanks > > > Brad > > > I wonder where is the > > > return( 0 ); > > > statement. > > Well, it does not quite solve the problem. In fact, the issue here is > const-correctness, because ctest() must be used as const, but ctest > has ctest& or int as arguments, being the second the only possible the > compiler tryes to find a conversion. The following does not compile: > > #include <iostream> > > class ctest { > public: > ctest(void) { std::cout << "ctest default constor" << > std::endl; }; > ctest(ctest& c) { std::cout <<"ctest copy constr" << > std::endl; }; > //ctest(int a) { std::cout <<"ctest int constor" << > std::endl; }; > > ctest& operator= (ctest& a) { std::cout << "ctest copy > assignment" << std::endl; return *this; }; > //operator int() { std::cout << "call operator int()" > << std::endl; return 20; } > > }; > > int main(void) > { > ctest cc = ctest(); > return( 0 ); > > } > > but the following does: > > #include <iostream> > > class ctest { > public: > ctest(void) { std::cout << "ctest default constor" << > std::endl; }; > ctest(const ctest& c) { std::cout <<"ctest copy > constr" << std::endl; }; > ctest(int a) { std::cout <<"ctest int constor" << > std::endl; }; > > ctest& operator= (ctest& a) { std::cout << "ctest copy > assignment" << std::endl; return *this; }; > operator int() { std::cout << "call operator int()" << > std::endl; return 20; } > > }; > > int main(void) > { > ctest cc = ctest(); > return( 0 ); > > } > > and prints > > ctest default constor > > only once, because of optimization, I guess. Forget to mention, I use Microsoft C/C++ Optimizing Compiler Version 14.00.50727.42 without any optimization option. I comment out ctest(int a) and operator int() it still compiles. And the execution output is "ctest default constor" From your reply and my understanding right now, ctest cc = ctest() has two part. First part is that ctest() will create a temp ctest object using default constructor. And second part is to create object cc using copy constructor with that temp ctest as argument. Because that temp ctest is a const, and my original class definition has no const- copy constructor; so compiler convert that temp ctest into int and use ctest(int a) to create object cc. But why it still compiles after comment out ctest(int a) and operator int()? And, after I add const to copy constructor like this: ctest(const ctest& c) { cout <<"ctest copy constr" << endl; }, why it doesn't output "ctest copy constr"? |
|
|
|
#6 |
|
Messages: n/a
Hébergeur: |
hill.liu@gmail.com wrote:
> On Jul 1, 11:49 am, Elias Salomão Helou Neto <eshn...@gmail.com> > wrote: >> On 1 jul, 00:24, Elias Salomão Helou Neto <eshn...@gmail.com> wrote: >> >> >> >> > On 1 jul, 00:16, "hill....@gmail.com" <hill....@gmail.com> wrote: >> >> > > Hi, >> >> > > I stuck into this problem that I can't figure it out. >> > > Here is the class definition: >> >> > > class ctest { >> > > public: >> > > ctest(void) { cout << "ctest default constor" << >> > > endl; }; ctest(ctest& c) { cout <<"ctest copy constr" >> > > << endl; }; ctest(int a) { cout <<"ctest int constor" >> > > <<endl; }; >> >> > > ctest& operator= (ctest& a) { cout << "ctest copy >> > > assignment" << >> > > endl; return *this; }; >> > > operator int() { cout << "call operator int()" >> > > <<endl; return 20; } >> >> > > }; >> >> > > int main(void) >> > > { >> > > ctest cc = ctest(); >> >> > > } >> >> > > And it outputs as following: >> > > ctest default constor >> > > call operator int() >> > > ctest int constor >> >> > > I wonder why it will invoke "operator int()" and call "constructor >> > > with int as argument". >> >> > > Thanks >> > > Brad >> >> > I wonder where is the >> >> > return( 0 ); >> >> > statement. >> >> Well, it does not quite solve the problem. In fact, the issue here is >> const-correctness, because ctest() must be used as const, but ctest >> has ctest& or int as arguments, being the second the only possible the >> compiler tryes to find a conversion. The following does not compile: >> >> #include <iostream> >> >> class ctest { >> public: >> ctest(void) { std::cout << "ctest default constor" << >> std::endl; }; >> ctest(ctest& c) { std::cout <<"ctest copy constr" << >> std::endl; }; >> //ctest(int a) { std::cout <<"ctest int constor" << >> std::endl; }; >> >> ctest& operator= (ctest& a) { std::cout << "ctest copy >> assignment" << std::endl; return *this; }; >> //operator int() { std::cout << "call operator int()" >> << std::endl; return 20; } >> >> }; >> >> int main(void) >> { >> ctest cc = ctest(); >> return( 0 ); >> >> } >> >> but the following does: >> >> #include <iostream> >> >> class ctest { >> public: >> ctest(void) { std::cout << "ctest default constor" << >> std::endl; }; >> ctest(const ctest& c) { std::cout <<"ctest copy >> constr" << std::endl; }; >> ctest(int a) { std::cout <<"ctest int constor" << >> std::endl; }; >> >> ctest& operator= (ctest& a) { std::cout << "ctest copy >> assignment" << std::endl; return *this; }; >> operator int() { std::cout << "call operator int()" << >> std::endl; return 20; } >> >> }; >> >> int main(void) >> { >> ctest cc = ctest(); >> return( 0 ); >> >> } >> >> and prints >> >> ctest default constor >> >> only once, because of optimization, I guess. > > Forget to mention, I use Microsoft C/C++ Optimizing Compiler Version > 14.00.50727.42 without any optimization option. > I comment out ctest(int a) and operator int() it still compiles. And > the execution output is > "ctest default constor" > > From your reply and my understanding right now, ctest cc = ctest() has > two part. First part is that ctest() will create a temp ctest object > using default constructor. And second part is to create object cc > using copy constructor with that temp ctest as argument. Because that > temp ctest is a const, and my original class definition has no const- > copy constructor; so compiler convert that temp ctest into int and use > ctest(int a) to create object cc. That understanding is not entirely correct. The temporary ctest() is _not_ const. If ctest had a non-const member function foo(), you could do ctest().foo() and the compiler would not complain. The misconception that temporaries are const stems from the provisions in [8.5.3/5] that prohibit initializing a non-const reference from a temporary. Your copy constructor takes its argument as a non-const reference and since the compiler cannot use the temporary ctest() to initialize it, it rejects this option. > But why it still compiles after comment out ctest(int a) and operator > int()? It doesn't. You also have to change the copy constructor. > And, after I add const to copy constructor like this: ctest(const > ctest& c) { cout <<"ctest copy constr" << endl; }, why it doesn't > output "ctest copy constr"? Because the compiler is allowed to optimize the copy constructor call away even if that changes the observable behavior of the program. Best Kai-Uwe Bux |
|
|
|
#7 |
|
Messages: n/a
Hébergeur: |
On Jul 1, 1:12 pm, Kai-Uwe Bux <jkherci...@gmx.net> wrote:
> hill....@gmail.com wrote: > > On Jul 1, 11:49 am, Elias Salomão Helou Neto <eshn...@gmail.com> > > wrote: > >> On 1 jul, 00:24, Elias Salomão Helou Neto <eshn...@gmail.com> wrote: > > >> > On 1 jul, 00:16, "hill....@gmail.com" <hill....@gmail.com> wrote: > > >> > > Hi, > > >> > > I stuck into this problem that I can't figure it out. > >> > > Here is the class definition: > > >> > > class ctest { > >> > > public: > >> > > ctest(void) { cout << "ctest default constor" << > >> > > endl; }; ctest(ctest& c) { cout <<"ctest copy constr" > >> > > << endl; }; ctest(int a) { cout <<"ctest int constor" > >> > > <<endl; }; > > >> > > ctest& operator= (ctest& a) { cout << "ctest copy > >> > > assignment" << > >> > > endl; return *this; }; > >> > > operator int() { cout << "call operator int()" > >> > > <<endl; return 20; } > > >> > > }; > > >> > > int main(void) > >> > > { > >> > > ctest cc = ctest(); > > >> > > } > > >> > > And it outputs as following: > >> > > ctest default constor > >> > > call operator int() > >> > > ctest int constor > > >> > > I wonder why it will invoke "operator int()" and call "constructor > >> > > with int as argument". > > >> > > Thanks > >> > > Brad > > >> > I wonder where is the > > >> > return( 0 ); > > >> > statement. > > >> Well, it does not quite solve the problem. In fact, the issue here is > >> const-correctness, because ctest() must be used as const, but ctest > >> has ctest& or int as arguments, being the second the only possible the > >> compiler tryes to find a conversion. The following does not compile: > > >> #include <iostream> > > >> class ctest { > >> public: > >> ctest(void) { std::cout << "ctest default constor" << > >> std::endl; }; > >> ctest(ctest& c) { std::cout <<"ctest copy constr" << > >> std::endl; }; > >> //ctest(int a) { std::cout <<"ctest int constor" << > >> std::endl; }; > > >> ctest& operator= (ctest& a) { std::cout << "ctest copy > >> assignment" << std::endl; return *this; }; > >> //operator int() { std::cout << "call operator int()" > >> << std::endl; return 20; } > > >> }; > > >> int main(void) > >> { > >> ctest cc = ctest(); > >> return( 0 ); > > >> } > > >> but the following does: > > >> #include <iostream> > > >> class ctest { > >> public: > >> ctest(void) { std::cout << "ctest default constor" << > >> std::endl; }; > >> ctest(const ctest& c) { std::cout <<"ctest copy > >> constr" << std::endl; }; > >> ctest(int a) { std::cout <<"ctest int constor" << > >> std::endl; }; > > >> ctest& operator= (ctest& a) { std::cout << "ctest copy > >> assignment" << std::endl; return *this; }; > >> operator int() { std::cout << "call operator int()" << > >> std::endl; return 20; } > > >> }; > > >> int main(void) > >> { > >> ctest cc = ctest(); > >> return( 0 ); > > >> } > > >> and prints > > >> ctest default constor > > >> only once, because of optimization, I guess. > > > Forget to mention, I use Microsoft C/C++ Optimizing Compiler Version > > 14.00.50727.42 without any optimization option. > > I comment out ctest(int a) and operator int() it still compiles. And > > the execution output is > > "ctest default constor" > > > From your reply and my understanding right now, ctest cc = ctest() has > > two part. First part is that ctest() will create a temp ctest object > > using default constructor. And second part is to create object cc > > using copy constructor with that temp ctest as argument. Because that > > temp ctest is a const, and my original class definition has no const- > > copy constructor; so compiler convert that temp ctest into int and use > > ctest(int a) to create object cc. > > That understanding is not entirely correct. The temporary > > ctest() > > is _not_ const. If ctest had a non-const member function foo(), you coulddo > > ctest().foo() > > and the compiler would not complain. > > The misconception that temporaries are const stems from the provisions in > [8.5.3/5] that prohibit initializing a non-const reference from a > temporary. Your copy constructor takes its argument as a non-const > reference and since the compiler cannot use the temporary ctest() to > initialize it, it rejects this option. > > > But why it still compiles after comment out ctest(int a) and operator > > int()? > > It doesn't. You also have to change the copy constructor. > > > And, after I add const to copy constructor like this: ctest(const > > ctest& c) { cout <<"ctest copy constr" << endl; }, why it doesn't > > output "ctest copy constr"? > > Because the compiler is allowed to optimize the copy constructor call away > even if that changes the observable behavior of the program. > > Best > > Kai-Uwe Bux Now I know why my original class definition will produce those outputs.:-) But I refine class definition like Elias suggested: class ctest { public: ctest(void) { std::cout << "ctest default constor" << std::endl; }; ctest(ctest& c) { std::cout <<"ctest copy constr" << std::endl; }; ctest& operator= (ctest& a) { std::cout << "ctest copy assignment" << std::endl; return *this; }; }; I build this successfully under Visual Studio 2005 and "ctest cc = ctest()" outputs "ctest default constor". Why is that? |
|
|
|
#8 |
|
Messages: n/a
Hébergeur: |
On Jul 1, 5:16 am, "hill....@gmail.com" <hill....@gmail.com> wrote:
> I stuck into this problem that I can't figure it out. > Here is the class definition: > class ctest { > public: > ctest(void) { cout << "ctest default constor" << endl; }; > ctest(ctest& c) { cout <<"ctest copy constr" << endl; }; > ctest(int a) { cout <<"ctest int constor" <<endl; }; > > ctest& operator= (ctest& a) { cout << "ctest copy assignment" << > endl; return *this; }; > operator int() { cout << "call operator int()" <<endl; return 20; } > > }; > > int main(void) > { > ctest cc = ctest(); > > } > > And it outputs as following: > ctest default constor > call operator int() > ctest int constor > I wonder why it will invoke "operator int()" and call "constructor > with int as argument". Because that's what is required by the standard. Because the source type is the same as the target type, the copy initialization basically becomes the same as direct initialization, e.g. as if you'd written ctest cc( ctest() ) ; The only constructor which can be called is the one taking an int, so the compiler converts your expression into an int, using the user defined conversion operator, and calls it. Maybe you meant for the copy constructor (and the assignment operator, while we're at it, although it isn't used in your example) to take references to const, as is the normal case. -- James Kanze (GABI Software) email:james.kanze@gmail.com Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34 |
|
![]() |
| Outils de la discussion | |
|
|