#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。