开发者

const reference to temporary and copying - C++

开发者 https://www.devze.com 2022-12-22 11:58 出处:网络
Please consider the following code, struct foo { foo() { std::cout << \"Constructing!\" << std::endl;

Please consider the following code,

struct foo
{
    foo()
    {
        std::cout << "Constructing!" << std::endl;
    }

    foo(const foo& f)
    {
        std::cout << "Copy constructing!" << std::endl;
    }

    ~foo()
    {
        std::cout << "Destructing.." << std::endl;
    }
};

foo get()
{
    foo f;
    return f;
}

int main()
{
    const foo& f = get();
    std::cout << "before return" << std::endl;
    return 0;
}

Output on MSVC

Constructing!
Copy constructing!
Destructing..
before return
Destructing..

Output of GCC

Constructing!
before return
Destructing..

The result which comes on MSVC looks incorrect.

Questions

  1. AFAIK, GCC produces the correct result here. Why MSVC is giving different results and why it is doing copy construction?
  2. const foo& f = get() and const foo f = get() produces same output because of return value optimization. In this case, which way of writing should be preferred?
  3. 开发者_开发百科

Any thoughts..


Your MSVC build has no optimizations on. Turn them on, you'll get identical output for both.

GCC is merely performing, by default, RVO on your temporary. It's basically doing:

const foo& f = foo();

MSVC is not. It's making the foo in the function, copying it to the outside the function (ergo the copy-constructor call), destructing the inner foo, then binds the reference.

Both outputs are correct. RVO is one instance where the standard explicitly allows the observable behavior of the program to change.


You are seeing the return value optimization, which is one kind of copy elision. Both programs are correct; the compiler is specifically given the option of eliminating a temporary which only serves to move data from one permanent object to another.


The get() function is Constructing the local (print Constructing!), and returning a Foo object by value. The Foo object being returned must be created and is done so via copy construction (print Copy constructing!). Note that this is the object value assigned to the const foo & f in main.

Before that assignment takes place though, the function must return from get() and local variables (i.e. foo f; in get()) must be destroyed. (print 1st Destructing..) From there the program terminates (i.e. returns from main) then the object returned by get() and assigned to "f" is destroyed. (print 2nd Destructing...)

The reason you're seeing different output for the two compilers is that GCC is optimizing the return value for get() and is simply replacing const foo &f = get() to const foo &f = foo;


1) This happens because of different optimization strategy. Because you don't have operator=, MSVC can restructure code to something like const foo& f(get()) therefore executing copy onstructor. 2) Depends on what you want to acheive:

const foo& f = get();
f = get(); // Incorrect, const references cannot be reassigned.
const foo g = get();
g = get(); // Correct.
0

精彩评论

暂无评论...
验证码 换一张
取 消