我刚刚听完了Scott Meyers关于C++ 0x的软件工程电台播客采访.大多数新功能对我来说都很有意义,我现在对C++ 0x感到兴奋,除了一个.我仍然没有得到移动语义 ......它们究竟是什么?
如果必须返回i,以下代码(func1())是否正确?我记得在某处读到返回对局部变量的引用时存在问题.它与func2()有什么不同?
int& func1()
{
int i;
i = 1;
return i;
}
int* func2()
{
int* p;
p = new int;
*p = 1;
return p;
}
Run Code Online (Sandbox Code Playgroud) 在许多情况下,从函数返回局部时,RVO会启动.但是,我认为显式使用std::move至少会在RVO未发生时执行移动,但RVO仍然会在可能的情况下应用.但是,似乎情况并非如此.
#include "iostream"
class HeavyWeight
{
public:
HeavyWeight()
{
std::cout << "ctor" << std::endl;
}
HeavyWeight(const HeavyWeight& other)
{
std::cout << "copy" << std::endl;
}
HeavyWeight(HeavyWeight&& other)
{
std::cout << "move" << std::endl;
}
};
HeavyWeight MakeHeavy()
{
HeavyWeight heavy;
return heavy;
}
int main()
{
auto heavy = MakeHeavy();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我用VC++ 11和GCC 4.71,debug和release(-O2)配置测试了这段代码.永远不会调用复制文件.移动ctor仅在调试配置中由VC++ 11调用.实际上,特别是这些编译器似乎都很好,但据我所知,RVO是可选的.
但是,如果我明确使用move:
HeavyWeight MakeHeavy()
{
HeavyWeight heavy;
return std::move(heavy);
}
Run Code Online (Sandbox Code Playgroud)
移动ctor总是被称为.因此,试图使其"安全"会使情况变得更糟.
我的问题是:
- 为什么要std::move预防RVO?
- 何时更好地"希望最好"并依赖RVO,何时应该明确使用 …
考虑以下类,实现移动构造函数的正确方法是什么:
class C {
public:
C();
C(C&& c);
private:
std::string string;
}
Run Code Online (Sandbox Code Playgroud)
当然,这个想法是避免复制string或解除分配两次.
让我们假设基本的例子只是为了清晰,我确实需要一个移动构造函数.
我试过了:
C::C(C&& c) {
//move ctor
string = std::move(c.string);
}
Run Code Online (Sandbox Code Playgroud)
和
C::C(C&& c) : string(std::move(c.string)) {
//move ctor
}
Run Code Online (Sandbox Code Playgroud)
两者都在gcc 4.8上编译正常并运行良好.这似乎选项A是正确的行为,string被复制,而不是使用选项B.移动
这是正确执行的举动构造的?