函数返回值和右值引用绑定

时间:2021-07-23 05:28:59

I'm trying to understand move semantics and perfect forwarding in C++ To do this I made next simple program:

我试图理解移动语义和C ++中的完美转发为此我做了下一个简单的程序:

#include <iostream>

struct Test
{
    Test(){ std::cout << "Test()" << std::endl; }
    Test(Test&&){ std::cout << "Test(Test&&)" << std::endl; }
    Test(const Test&){ std::cout << "Test(const Test&)" << std::endl; }

    ~Test(){ std::cout << "~Test()" << std::endl; }
};

Test MakeTest()
{
    Test t;//output Test()

    return Test(t);//output Test(const Test&)
}//output ~Test

int main()
{
    std::cout << "------------------------------" << std::endl;
    Test t0(MakeTest()); //How is t0 constructed!??
    std::cout << "------------------------------" << std::endl;
    Test t1(std::forward<Test>(MakeTest())); //output Test(Test&&) \n ~Test
    std::cout << "------------------------------" << std::endl;

    return 0;
}//output ~Test \n ~Test

The program has following output(VS2013, GCC 4.8 - debug mdoe, optimizations turned off):

该程序具有以下输出(VS2013,GCC 4.8 - 调试mdoe,关闭优化):

------------------------------
Test()
Test(const Test&)
~Test()
------------------------------
Test()
Test(const Test&)
~Test()
Test(Test&&)
~Test()
------------------------------
~Test()
~Test()

What I don't understand here is how t0 is constructed. I expected to be constructed using Test(Test&&) as return value of MakeTest() is unnamed temporary value.

这里我不明白的是如何构造t0。我希望使用Test(Test &&)构造,因为MakeTest()的返回值是未命名的临时值。

Can you please explain why it does not call any of the 3 constructors I defined?

你能解释为什么它不调用我定义的3个构造函数中的任何一个吗?

1 个解决方案

#1


-1  

@Angew's comment is most probably right, copy/move elision must be charge.

@Angew的评论最可能是正确的,复制/移动elision必须收费。

Another point can be that even though Test(t) is temporary, it is still a value, and thus the copy constructor is a closer match.

另一点可能是即使Test(t)是临时的,它仍然是一个值,因此复制构造函数更接近匹配。

Anyhow if you want the move constructor to be used for sure, you can use std::move().

无论如何,如果你想确保使用移动构造函数,你可以使用std :: move()。

Test MakeTest()
{
    Test t;
    return std::move(Test(t));
}

I used this several times because once we are using move constructors, there could easily be tricks in constructors, we do want to be called.

我多次使用它,因为一旦我们使用移动构造函数,构造函数中很容易出现问题,我们确实希望被调用。

#1


-1  

@Angew's comment is most probably right, copy/move elision must be charge.

@Angew的评论最可能是正确的,复制/移动elision必须收费。

Another point can be that even though Test(t) is temporary, it is still a value, and thus the copy constructor is a closer match.

另一点可能是即使Test(t)是临时的,它仍然是一个值,因此复制构造函数更接近匹配。

Anyhow if you want the move constructor to be used for sure, you can use std::move().

无论如何,如果你想确保使用移动构造函数,你可以使用std :: move()。

Test MakeTest()
{
    Test t;
    return std::move(Test(t));
}

I used this several times because once we are using move constructors, there could easily be tricks in constructors, we do want to be called.

我多次使用它,因为一旦我们使用移动构造函数,构造函数中很容易出现问题,我们确实希望被调用。