Zian said:
So are you saying that when a new object is being created, whether a
default/overloaded constructor is called or a copy constructor is
called is compiler dependent?
Well, that's not the full story. See below.
That seems a little perplexing..
Suppose I want to keep count of how many new objects are being
created, and how many times a copy is made. So just having counters in
the default/overloaded/copy constuctors is not reliable enough?
Yes, it is reliable. The idea is that under certain circumstances, if you
create a temporary and then copy-construct a variable from it, the compiler
is allowed to eliminate that temporary (and thus its construction and - for
that matter - its destruction) and instead directly construct the variable.
So your counter will still work. The copy constructor is simply not called
because no copy is made. Remember, each object gets constructed exactly
once and destoyed exactly once.
Consider this:
struct Foo
{
Foo(const Foo&);
Foo(int);
int data;
};
Foo operator+(const Foo& lhs, const Foo& rhs)
{
return Foo(lhs.data + rhs.data);
}
int main()
{
Foo a = 3;
Foo b = 5;
Foo f = a + b;
}
Without return value optimization, the compiler would need two calls to the
copy constructor. First operator+ creates a temporary Foo that gets copied
on returning. Then, f is copy constructed from that return value.
Now the compiler is allowed to elide one or both of those copies and let
operator+ directly construct f as a shortcut. Basically, this is done by
main just providing the address of f (before it actually is constructed) to
operator+ as a hidden parameter. Then operator+ doesn't use its own local
memory for the temporary Foo, but instead uses the address of f to
construct it.