[C++] 右值引用作为参数传递

#include <iostream>
class Data
{
  public:
    Data() { std::cout << "construction ++ " << std::endl; }
    ~Data() { std::cout << "destruction -- " << std::endl; }

    Data(const Data &) { std::cout << "copy construct" << std::endl; }
    Data &operator=(const Data &) { std::cout << "copy= construct" << std::endl; }

    Data(Data &&) { std::cout << "move construct" << std::endl; }
    Data &operator=(const Data &&) { std::cout << "move= construct" << std::endl; }
};

class Foo
{
  public:
    Foo(Data data) : m_data(data) { std::cout << "Foo done " << std::endl; }

    Data m_data;
};

int main()
{
    Data d = Data();
    Foo f = Foo(d);
}

输出:

construction ++ 
copy construct
copy construct
Foo done 
destruction -- 
destruction -- 
destruction -- 

两次拷贝构造,效率极低

修改1:

class Foo
{
  public:
    Foo(Data data) : m_data(std::move(data)) { std::cout << "Foo done " << std::endl; }

    Data m_data;
};

int main()
{
    Data d = Data();
    Foo f = Foo(d);
}
construction ++ 
copy construct
move construct
Foo done 
destruction -- 
destruction -- 
destruction --

修改2:

class Foo
{
  public:
    Foo(Data &&data) : m_data(std::move(data)) { std::cout << "Foo done " << std::endl; }

    Data m_data;
};

int main()
{
    Data d = Data();
    Foo f = Foo(std::move(d));
}
construction ++ 
move construct
Foo done 
destruction -- 
destruction -- 

修改3:

class Foo
{
  public:
    Foo(Data &&data) : m_data(std::forward<Data>(data)) { std::cout << "Foo done " << std::endl; }

    Data m_data;
};

int main()
{
    Data d = Data();
    Foo f = Foo(std::move(d));
}

construction ++ 
move construct
Foo done 
destruction -- 
destruction -- 

总结:
如果构造函数参数传入使用值拷贝,赋值使用move,那么作用就是
从两次copy构造 -> 一次copy构造 + 一次move构造
如果构造函数参数传入使用右值引用,赋值使用move,那么作用就是
从两次copy构造 -> 只有一个move构造
并且在这种情况下,可以使用 std::forward<Data>(data) 替代std::move。

注意,使用std::move进行优化的时候,一定要确认变量本身是否支持移动构造语义,否则没有任何意义,比如char,int类型的变量。另外,std::string虽然支持移动构造,由于"SSO"优化,只要在长度至少是16时生效,才会在堆上构建,详细见https://stackoverflow.com/questions/54420470/does-stdstring-move-constructor-actually-move

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容