C 11:没有触发移动构造器
C++11: Move constructor is not triggered
最近我一直在研究C 11中的移动语义。我给我留下了深刻的印象,我迫不及待地想把我的手弄脏并尝试。以下是我的代码:
#include <iostream>
using namespace std;
class ArrayWrapper
{
public:
// default constructor produces a moderately sized array
ArrayWrapper ()
: _p_vals( new int[ 64 ] )
, _size( 64 )
{
cout << "Default constructor: " << this << endl;
}
explicit ArrayWrapper (int n)
: _p_vals( new int[ n ] )
, _size( n )
{
cout << "Constructor: " << this << endl;
}
// move constructor
ArrayWrapper (ArrayWrapper&& other)
: _p_vals( other._p_vals )
, _size( other._size )
{
cout << "Move constructor: " << this << endl;
other._p_vals = NULL;
other._size = 0;
}
// copy constructor
ArrayWrapper (const ArrayWrapper& other)
: _p_vals( new int[ other._size ] )
, _size( other._size )
{
cout << "Copy constructor: " << this << endl;
for ( int i = 0; i < _size; ++i )
{
_p_vals[ i ] = other._p_vals[ i ];
}
}
~ArrayWrapper ()
{
cout << "Destructor: " << this << endl;
delete [] _p_vals;
}
void self () {
cout << "This address: " << this << endl;
}
public:
int *_p_vals;
int _size;
};
ArrayWrapper two() {
ArrayWrapper a(7);
cout << "Temp ArrayWrapper created!" << endl;
return a;
}
int main() {
ArrayWrapper b (two());
b.self();
}
(我引用了1个代码)
代码看起来很长,但实际上很天真,只是一个转储数组。
在第67行上,我故意创建了b,并期望看到如何调用移动构造器。但令人失望的是,该程序的输出是:
Constructor: 0x7fff51d60be0
Temp ArrayWrapper created!
This address: 0x7fff51d60be0
Destructor: 0x7fff51d60be0
打印的三个地址是相同的,并且根本不调用移动构造函数!实际上,我后来尝试删除MOVE构造函数,并且该程序仍然进行了编译,并给出了相同的输出!而且,如果您仔细看一看,您会发现构造函数仅在构造时调用一次。也就是说,当b构造b时,根本没有构造函数,也没有移动或复制!
我真的很困惑。谁能告诉我为什么没有触发移动构造函数,以及如何构建地球b?
这是因为RVO(返回值优化)技巧。ArrayWrapper two();
的对象代替ArrayWrapper b;
。这就是为什么只有一个结构 破坏的原因。
尝试将其修改为:
ArrayWrapper two(bool disable_rvo) {
ArrayWrapper a(7);
cout << "Temp ArrayWrapper created!" << endl;
if (disable_rvo)
return a;
else
return ArrayWrapper(8);
}
int main() {
ArrayWrapper b (two(true));
b.self();
}
并关闭优化。
您所经历的被称为复制elision-复制和移动构造函数可以在某些情况下跳过,即使跳过它们会具有可观察到的副作用。常见案例包括RVO和NRVO(返回值优化和命名RVO)或来自匿名临时性的复制限制。
阻止它,在您从函数返回的点上明确调用std::move
,以及在main
中构造值的位置,因为std::move
的rvalue cast cast cast cast cons cons cons cast cast cast cast cast cast casts cons cast cast cast cons cons cons cast conts cons cost cast cost cast conts cons cost cast contssion的rvalue cast cast cast cast cast cast cast cast cast cast的。std::move
采用T&
或T&&
,并以防止"左手侧"执行力流的方式将其转变为T&&
,因为(至少在此时)将ELISION限制为某些窄情况。
通常是一个坏主意,但是std::move
会做到。
- 为什么不调用移动构造函数?(默认情况下只有构造器,没有别的)
- std::vector::p ush_back() 不会在 MSVC 上编译具有已删除移动构造函数的对象
- 仅包含可移动 std::map 的类的移动构造函数不起作用
- 为什么调用复制构造函数而不是移动构造函数?
- 基类中的默认析构函数禁用子类中的移动构造函数(如果有成员)
- 从具有按值捕获的 lambda 移动构造 std::函数时,移动构造函数调用两次
- 从其他容器中移动构造"std::map"
- 移动构造函数和右值引用
- 为什么 std::memmove 中联合的默认非平凡移动构造函数C++?
- 为什么协程的返回类型必须是可移动构造的?
- 具有专用化的模板类中的可靠条件复制和移动构造函数
- C++:为什么不调用移动构造函数?
- 移动构造函数永远不会被调用
- C++:关于使用 Stroustrup 示例移动构造函数/赋值的问题
- UNORDERED_MAP的存在确定是否使用了复制构建器或移动构造器
- 移动构造器的力测试
- 无法使用迭代器擦除矢量元素,矢量元素实现移动构造函数
- 如何声明包装器类型 X 的移动构造函数<T> noexcept 取决于is_nothrow_move_constructible<T>?
- C 11:没有触发移动构造器
- 只能在析构函数中释放一次的资源的惯用移动构造器