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

时间:2017-05-17 16:46:58

标签: c++ c++11

我有以下类型的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:'std :: pair :: pair':函数不带   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也有它的副本/分配私人。但我仍然不明白为什么用'}替换'default'修正了。请解释。

2 个答案:

答案 0 :(得分:2)

您的问题是FooObject的某个成员无法移动,这会阻止编译器生成默认移动操作。

您自己实施的移动操作的{}版本无法工作(特别是:它们实际上并不执行移动操作)FooObject的成员因此是合法的。

答案 1 :(得分:1)

之间的区别
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的移动构造函数中实际上没有移动任何内容。