我正在尝试理解C++ 11中的移动语义,并且我编写了一小段代码来检查在创建对象时调用哪些构造函数.
这是代码:
#include <iostream>
using namespace std;
class Bar
{
public:
int b;
Bar();
Bar(const Bar&);
~Bar();
};
class Foo
{
public:
int d;
Bar* b;
Foo();
Foo(const Foo&);
Foo(Foo&& other);
~Foo();
Foo& operator = (Foo);
};
Foo test();
Foo::Foo()
{
cout << "Default ctr of foo called\n";
b = new Bar();
}
Foo::~Foo()
{
delete b;
}
Foo::Foo(const Foo& other)
{
cout << "Copy ctr of foo called\n";
d = other.d;
b = new Bar();
b->b = other.b->b;
}
Foo::Foo(Foo&& other)
{
cout << "Move ctr of foo called\n";
d = other.d;
b = other.b;
other.d = 0;
other.b = NULL;
}
Foo& Foo::operator = (Foo other)
{
cout << "Copy assignment of foo called\n";
d = other.d;
b = new Bar();
b->b = other.b->b;
return *this;
}
Bar::Bar()
{
b = 1;
}
Bar::~Bar()
{
}
Bar::Bar(const Bar& other)
{
b = other.b;
}
int main()
{
Bar b;
Foo f1;
Foo f = test();
Foo f3 = move(test());
// cout << f1.b->b << "\n";
// Foo f2(test());
return 0;
}
Foo test()
{
Foo f;
return f;
}
Run Code Online (Sandbox Code Playgroud)
这是我得到的输出:
Default ctr of foo called
Default ctr of foo called
Default ctr of foo called
Move ctr of foo called
Run Code Online (Sandbox Code Playgroud)
我不太清楚为什么没有为Foo f调用移动构造函数.是不是test()是一个右值?在这种情况下调用哪个构造函数?
任何帮助将不胜感激.
你在这里看到的是复制省略的影响.复制省略是标准指定的优化,它使编译器在从堆栈返回对象的情况下,使函数在调用者的堆栈空间中构建对象,并绕过复制并完全移动构造函数,而不管是哪一方影响.在您的情况下,副作用是构造函数将打印到的cout.
我们可以通过使用例如a unique_ptr来在堆上创建对象来阻止编译器使用此快捷方式.它涉及的更多,但它可以得到你期望的结果:
#include <unique_ptr>
Foo test()
{
unique_ptr<Foo> f(new Foo);
return move(*f);
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,你需要移动指针,f因为它unique_ptr的operator*返回引用,而不是临时的.如果你不移动它,它将调用复制构造函数.
| 归档时间: |
|
| 查看次数: |
234 次 |
| 最近记录: |