编译器是否优化了默认移动构造函数?

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;

copy/assign 构造函数是私有的,以禁用隐式复制。

所以我应该能够像这样在地图中放置一对:

mymap.emplace(std::make_pair(false,32),FooObject());

这会抛出一个错误列表,最后一个是:

error C2660: 'std::pair::pair': function does not take 2 arguments

如果我在没有 "default" 的情况下声明移动复制分配构造函数 然后编译就ok了。

   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 也有它的 copy/assign private.But 我仍然不明白为什么用 {} 替换 'default' 修复 that.Please 解释。

您的问题是 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_f\n";
    Foo test_f(std::move(f));
    std::cout << "test_b\n";
    Bar test_b(std::move(b));
}

输出

test_f
in Moveable(Moveable&&)
test_b

Live Example

表明在 Bar 的移动构造函数中实际上没有移动任何东西。