NPS
NPS

Reputation: 6355

Unpredictable copy elision?

According to this Wiki page the following code:

#include <iostream>

struct C {
  C() = default;
  C(const C&) { std::cout << "A copy was made.\n"; }
};

C f() {
  return C();
}

int main() {
  std::cout << "Hello World!\n";
  C obj = f();
}

may produce different outputs depending on the compiler and that compiler's settings.

How can I write programs if I cannot predict how they're going to behave (I cannot really know what any given compiler in any given version with any given settings will or will not optimize away)? Are there any general guidelines regarding copy-elision that I should follow?

Upvotes: 2

Views: 70

Answers (1)

Jarod42
Jarod42

Reputation: 217135

Write code that doesn't depend of presence or absence of copy-elision.

It is mainly to respect rule of 3/5/0.

Here, the main purpose of your class C is to exhibit copy-elision.

In regular case, class contains data and or manage resources. So then should implement correct copy/move constructors to maintains there invariant, avoid double delete, ...

And so removing a copy is just an optimization.

There are other constructs which might depend of compiler/build/run:

  • Order of evaluation of function argument is unspecified. You should write code which doesn't depend of the order of that evaluation.

    template <typename ... Ts> void any_order_call(Ts&&...){}
    
    std::ostream& hello() { return std::cout << "hello "; }
    std::ostream& world() { return std::cout << "world"; }
    
    void maybe_hello_world()
    {
        any_order_call(world(), hello());
    }
    

    So output might be

    hello world
    

    or

    worldhello 
    
  • sizeof(int) depends of compiler/architecture, you should not assume its size. For this one, you might have test for that (if (sizeof (int) == 4)) or (optional :( ) fixed-size types (std::int32_t, ...).

  • ...

Upvotes: 3

Related Questions