3
Line Line::operator =(Line ln) {
        cout << "Assignment operator\n";
        Line temp;
        temp.ptr = new int;
        *temp.ptr = *(ln.ptr);
        return temp;
    }

In the above piece of code, the copy constructor is not called when the following statement is executed:

return temp;

Since the return is by value, why is the copy constructor not called?

Thanks

Iceman
  • 4,202
  • 7
  • 26
  • 39
  • 3
    Your operator implementation is wrong: `operator=` should return a *reference* to `*this`, not a new object. – Konrad Rudolph Nov 23 '13 at 14:41
  • @Konrad: Thanks for pointing this out. So you mean: *this.ptr = *(ln.ptr); and return *this? – Iceman Nov 23 '13 at 14:43
  • Yes. The whole `temp` object is unnecessary. However, you should also not be using a (raw) pointer here to begin with. C++ provides better mechanisms. – Konrad Rudolph Nov 23 '13 at 14:44
  • @KonradRudolph: Thanks! I'm just using this code to demonstrate to myself some concepts – Iceman Nov 23 '13 at 14:46

3 Answers3

6

This is called copy elision: It is permissible to not make a copy when returning a local object by value, and instead the local object (your temp) is constructed directly in the caller. This is allowed even if the copy constructor has side effects.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
4

With the above set-up it is quite likely that the compiler elides the copy constructor and, instead, directly constructs the temporary temp in the location where the return value will be expected. Copy elision is explicitly allowed even if the copy constructor has side effects. However, even if the copy is elided, the copy or move constructor still has to be accessible, i.e., the potential of copy elision doesn't relax the rules on the corresponding constructor to be accessible.

If you feel you absolutely want to have a copy constructor called, you can force copy construction, e.g., by passing the result through an identity function:

template <typename T>
T const& identity(T const& object) {
    return object;
}
// ...
    return identity(temp);

Normally, you'd want the copy constructor to be elided, however.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • How does that function force copying? Won’t it simply be inlined and then the as-if rule takes effect? – Konrad Rudolph Nov 23 '13 at 14:42
  • @KonradRudolph: nope. The semantics are different and copy elision is allowed only in very specific cases (see 12.8 [class.copy] paragraph 31 for details): "... in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object ..." – Dietmar Kühl Nov 23 '13 at 14:45
  • 1
    @KonradRudolph: Copy elision is an exemption from the "as-if" rule. With the modified code, you're not returning a local variable, and so the exemption is no longer allowed. – Kerrek SB Nov 23 '13 at 14:46
3

I would like to append the previous posts with the remark that even the copy constructor is omitted in building the target object it must still be accessible and defined. If you for example will declrae your copy constructor as private when the compiler shall issue an error (except MS VC++ at least 2010 that has a bug:) )

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335