copy elision in c++03

Viewed 177

Copy-elision is, in some cases, mandatory in c++17, and permitted in c++11/14. This in particular concerns copy initialization. For example, the following program

#include <iostream>

struct A
{
  explicit A(int){ std::cout << "conversion" << std::endl; }
  A(const A&) { std::cout << "copy constructor" << std::endl; }
};

int main()
{
    A b = A(3);
}

is expected in c++17 to produce an output

conversion

and in c++11/14 may produce the same output. With these regards, both gcc 10.1.0 and clang 11.1.0 produce the output above also with -std=c++11 or -std=c++14, unless one explicitly disables the optional constructors elision with -fno-elide-constructors.

But what about c++03 standard? Was it allowed to elide the copy constructors in the copy initialization? gcc and clang with -std=c++03 always suppress the copy constructor (unless one specifies -fno-elide-constructors).

1 Answers

Yes, copy ellision is permitted in C++03 and C++98. That's the paragraph for C++98 and C++03:

Non-mandatory elision of copy operations

Under the following circumstances, the compilers are permitted, but not required to omit the copy construction of class objects even if the copy constructor and the destructor have observable side-effects. The objects are constructed directly into the storage where they would otherwise be copied to. This is an optimization: even when it takes place and the copy constructor is not called, it still must be present and accessible (as if no optimization happened at all), otherwise the program is ill-formed:

  • In a return statement, when the operand is the name of a non-volatile object with automatic storage duration, which isn't a function parameter or a catch clause parameter, and which is of the same class type (ignoring cv-qualification) as the function return type. This variant of copy elision is known as NRVO, "named return value optimization".

  • In the initialization of an object, when the source object is a nameless temporary and is of the same class type (ignoring cv-qualification) as the target object. When the nameless temporary is the operand of a return statement, this variant of copy elision is known as RVO, "return value optimization".

When copy elision occurs, the implementation treats the source and target of the omitted copy operation as simply two different ways of referring to the same object, and the destruction of that object occurs at the later of the times when the two objects would have been destroyed without the optimization

cppreference

I removed everything that's only valid since C++11.

The only differences between C++98, C++03 and C++11 regarding ellision are move operations and exception handling.

Related