?
=?ISO-8859-1?Q?Christian_Engstr=F6m?=
When i compile the program listed below with gcc version 3.3.1 (MinGW on
Windows XP) I get the following result:
Calling 'func(d)':
'base' copy constructor
Calling 'func(*d_handle)':
'base' copy constructor
Calling 'func(d_handle)':
'derived' copy constructor <-- Why?
'base' copy constructor
The problem is the call to the 'derived' copy constructor, which I don't
want and hadn't expected, and which Microsoft Visual C++ 6.0 doesn't
generate.
Is it the gcc or the MSVC compiler that is broken? I would naively have
assumed that MSVC is right and gcc is wrong in this case, but perhaps
there is something in the standard that prescribes the gcc behavior for
some reason?
My intention was that there shouldn't be any temporary 'derived' objects
created at all, since both the implicit conversion operator from
'derived_handle' to 'derived' and 'derived's operator* return references
to an existing 'derived' object.
After having recived some expert answers on this list on a somewhat
related question, I am nowadays aware of the rule that says that a
temporary object can't be tied to a non-const reference function
parameter, but that shouldn't have anything to do with this problem,
should it?
=======================================================================
#include <iostream>
//----------------------------------------------------------------------------
class base
{
public:
base() {}
base(const base&) {std::cout << " 'base' copy constructor" <<
std::endl;}
};
//----------------------------------------------------------------------------
class derived : public base
{
public:
derived() {}
derived(const derived&) {std::cout << " 'derived' copy constructor"
<< std::endl;}
};
//----------------------------------------------------------------------------
class derived_handle
{
derived* tptr;
public:
derived_handle() {};
derived_handle(derived* inptr) : tptr(inptr) {}
derived& operator*() const {return *tptr;}
derived* operator->() const {return tptr;}
operator derived&() const {return **this;} // Implicit conversion
to 'derived'
};
//----------------------------------------------------------------------------
void func(base b) {} // Takes the parameter by value
//============================================================================
int main (int argc, char* argv[])
{
derived d;
derived_handle d_handle(new derived());
std::cout << "\nCalling 'func(d)':" << std::endl;
func(d);
std::cout << "\nCalling 'func(*d_handle)':" << std::endl;
func(*d_handle);
std::cout << "\nCalling 'func(d_handle)':" << std::endl;
func(d_handle); // Calls 'derived' copy constructor with gcc (only)
return 0;
}
Windows XP) I get the following result:
Calling 'func(d)':
'base' copy constructor
Calling 'func(*d_handle)':
'base' copy constructor
Calling 'func(d_handle)':
'derived' copy constructor <-- Why?
'base' copy constructor
The problem is the call to the 'derived' copy constructor, which I don't
want and hadn't expected, and which Microsoft Visual C++ 6.0 doesn't
generate.
Is it the gcc or the MSVC compiler that is broken? I would naively have
assumed that MSVC is right and gcc is wrong in this case, but perhaps
there is something in the standard that prescribes the gcc behavior for
some reason?
My intention was that there shouldn't be any temporary 'derived' objects
created at all, since both the implicit conversion operator from
'derived_handle' to 'derived' and 'derived's operator* return references
to an existing 'derived' object.
After having recived some expert answers on this list on a somewhat
related question, I am nowadays aware of the rule that says that a
temporary object can't be tied to a non-const reference function
parameter, but that shouldn't have anything to do with this problem,
should it?
=======================================================================
#include <iostream>
//----------------------------------------------------------------------------
class base
{
public:
base() {}
base(const base&) {std::cout << " 'base' copy constructor" <<
std::endl;}
};
//----------------------------------------------------------------------------
class derived : public base
{
public:
derived() {}
derived(const derived&) {std::cout << " 'derived' copy constructor"
<< std::endl;}
};
//----------------------------------------------------------------------------
class derived_handle
{
derived* tptr;
public:
derived_handle() {};
derived_handle(derived* inptr) : tptr(inptr) {}
derived& operator*() const {return *tptr;}
derived* operator->() const {return tptr;}
operator derived&() const {return **this;} // Implicit conversion
to 'derived'
};
//----------------------------------------------------------------------------
void func(base b) {} // Takes the parameter by value
//============================================================================
int main (int argc, char* argv[])
{
derived d;
derived_handle d_handle(new derived());
std::cout << "\nCalling 'func(d)':" << std::endl;
func(d);
std::cout << "\nCalling 'func(*d_handle)':" << std::endl;
func(*d_handle);
std::cout << "\nCalling 'func(d_handle)':" << std::endl;
func(d_handle); // Calls 'derived' copy constructor with gcc (only)
return 0;
}