11

このコードでは:

#include <iostream>

using std::cout;

class Foo {
    public:
        Foo(): egg(0) {}
        Foo(const Foo& other): egg(1) {}

        int egg;
};

Foo bar() {
    Foo baz;
    baz.egg = 3;
    return baz;
}

int main(void) {
    Foo spam(bar());
    cout << spam.egg;
    return 0;
}

出力は ですが3、期待していたのは1です。

これは、コピー コンストラクターが行で呼び出されないことを意味しますFoo spam(bar())

bar関数が参照を返さないためだと思います。

の初期化時に実際に何が起こっているのか説明していただけますspamか?

それがばかげた質問である場合は、事前にお詫び申し上げます。

ありがとう!

4

1 に答える 1

19

Copy/move elision is the only allowed exception to the so-called "as-if" rule, which normally constrains the kinds of transformations (e.g. optimizations) that a compiler is allowed to perform on a program.

The rule is intended to allow compilers to perform any optimization they wish as long as the transformed program would work "as if" it was the original one. However, there is one important exception.

Per paragraph 12.8/31 of the C++11 Standard:

When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the constructor selected for the copy/move operation and/or the destructor for the object have side effects. [...] This elision of copy/move operations, called copy elision, is permitted in the following circumstances (which may be combined to eliminate multiple copies):

  • in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function or catch-clause parameter) with the same cv-unqualified type as the function return type, the copy/move operation can be omitted by constructing the automatic object directly into the function’s return value

[...]

  • 参照 (12.2) にバインドされていない一時クラス オブジェクトが同じ cv 非修飾型のクラス オブジェクトにコピー/移動される場合、一時オブジェクトをターゲットに直接構築することにより、コピー/移動操作を省略できます。省略されたコピー/移動の

[...]

つまり、 12.8/31 の規定が適用される場合に、コピー コンストラクターまたはムーブ コンストラクターが呼び出されるか呼び出されないことに依存するべきではありません。

于 2013-05-02T18:09:32.283 に答える