编译器是否优化了默认移动构造函数?
Is default move constructor optimized away by compiler?
我有一个以下类型的std::multimap:
typedef std::multimap<std::pair<bool,uint32_t>, FooObject>
FooObject具有默认的移动复制和赋值构造函数声明:
FooObject(FooObject&& v) = default;
FooObject& operator=(FooObject&& other)=default;
复制/赋值构造函数是私有的,用于禁用隐式复制。
所以我应该能够像这样在地图上放置一对:
mymap.emplace(std::make_pair(false,32),FooObject());
这将抛出一个错误列表,最后有一个错误:
错误 C2660:"标准::p空气::p空气":功能不采用 2 参数
如果我声明移动复制分配构造函数没有"默认" 然后它编译正常。
FooObject(FooObject&& v){}
FooObject& operator=(FooObject&& other){}
为什么?当标有"default"关键字时,编译器是否会优化这些构造函数?我正在使用MSVC140
更新:
根据下面的评论,我找到了原因 - FooObject 有一个不可复制的成员实例。 这是 FooObject:
#define NO_COPY_ASSIGN(TypeName)
TypeName (const TypeName &);
void operator= (const TypeName &);
class FooObject
{
private:
NO_COPY_ASSIGN(FooObject)
public:
struct FooStruct
{
FooBuffer frameBuffer; //<--Here it is
}fooStruct;
FooObject(){}
/** Move constructor to allow insert into vector without copy */
FooObject(FooObject&& v) = default;
FooObject& operator=(FooObject&& other) = default;
};
*FooBuffer也有它的复制/分配私有。但我仍然不明白为什么用 {} 替换"默认"可以解决这个问题。请解释一下。
您的问题是FooObject
的一个成员不可移动,这会阻止编译器生成默认的移动操作。
您自己实现的移动操作的{}
版本对FooObject
的成员不起作用(具体来说:它们实际上并不执行移动操作),因此是合法的。
两者之间的区别
FooObject(FooObject&& v) = default;
和
FooObject(FooObject&& v){}
是前者将发出一个构造函数,该构造函数将每个成员从v
中移出,而后者默认构造每个成员并且不对v
执行任何操作。
由于FooBuffer
是不可移动的,这意味着编译器将删除FooObject(FooObject&& v) = default;
因为它的格式不正确。
有了FooObject(FooObject&& v){}
,您就不会遇到这个问题,因为您永远不会尝试移动v
的成员。 由于没有成员初始化列表,编译器将为您添加一个仅默认构造成员的列表。
您可以通过以下方式更明确地看到此行为:
struct Moveable
{
Moveable() = default;
Moveable(Moveable&&) { std::cout << "in Moveable(Moveable&&)n"; }
};
struct Foo
{
Foo() = default;
Foo(Foo&&) = default;
Moveable m;
};
struct Bar
{
Bar() = default;
Bar(Bar&&){}
Moveable m;
};
int main()
{
Foo f;
Bar b;
std::cout << "test_fn";
Foo test_f(std::move(f));
std::cout << "test_bn";
Bar test_b(std::move(b));
}
哪些输出
test_f
in Moveable(Moveable&&)
test_b
现场示例
表明Bar
的移动构造函数中实际上没有移动任何内容。
- 为什么不调用移动构造函数?(默认情况下只有构造器,没有别的)
- std::vector::p ush_back() 不会在 MSVC 上编译具有已删除移动构造函数的对象
- 仅包含可移动 std::map 的类的移动构造函数不起作用
- 为什么调用复制构造函数而不是移动构造函数?
- 基类中的默认析构函数禁用子类中的移动构造函数(如果有成员)
- 从具有按值捕获的 lambda 移动构造 std::函数时,移动构造函数调用两次
- 移动构造函数和右值引用
- 为什么 std::memmove 中联合的默认非平凡移动构造函数C++?
- 具有专用化的模板类中的可靠条件复制和移动构造函数
- C++:为什么不调用移动构造函数?
- 移动构造函数永远不会被调用
- C++:关于使用 Stroustrup 示例移动构造函数/赋值的问题
- 运算符+ 的规范实现涉及额外的移动构造函数
- C ++为什么在移动构造函数中需要移动/前进
- 为什么在删除"移动构造函数"时使用"复制构造函数"?
- 为什么这里不调用移动构造函数?
- 隐式移动构造函数
- 如何为具有私有成员的派生类实现移动构造函数
- 为什么不调用移动构造函数
- 是否可以避免在以下代码中复制/移动构造函数的需要?