避免调用move构造函数

时间:2018-11-19 19:11:56

标签: c++ c++11 c++17

我有以下示例

#include <cstdint>

class FooC
{
public:
   FooC(uint16_t iPort, uint16_t iPin)
   : PORT(iPort)
   , PIN(iPin)
   {
   };

   ~FooC() = default;

   FooC() = delete;
   FooC(const FooC&) = delete;
   FooC(FooC&&) = delete;

private:
   const uint16_t PORT;
   const uint16_t PIN;
};

int main()
{
    FooC array[2] = {
       FooC(1,2),
       FooC(3,4)
    };
}

,我不想调用默认的,移动和复制构造函数。因此,我删除了功能。不幸的是,这导致以下错误(与C ++ 11一起编译)

  

:在函数'int main()'中:

     

:28:5:错误:使用已删除的功能'FooC :: FooC(FooC &&)'

 };

 ^
     

:16:4:注意:在此处声明

FooC(FooC&&) = delete;

^~~~
     

:28:5:错误:使用已删除的功能'FooC :: FooC(FooC &&)'

 };

 ^
     

:16:4:注意:在此处声明

FooC(FooC&&) = delete;

^~~~
     

编译器返回:1

在此示例中是否可以用参数强制调用构造函数,并且仍然删除默认的,移动和复制构造函数?

2 个答案:

答案 0 :(得分:14)

在C ++ 11和C ++ 14中,您可以使用嵌套的花括号:

FooC array[2] = {{1,2}, {3,4}};

在C ++ 17中,由于有了新的prvalue /物化规则(“保证复制省略”),您的代码应该已经可以正常工作。

答案 1 :(得分:5)

  

在此示例中是否可以用参数强制调用构造函数,并且仍然删除默认的,移动和复制构造函数?

使用当前语法(在C ++ 17之前)不可以,并且可以(在C ++ 17中)。

C ++ 17之前的版本:

这是不可能的。聚合初始化将初始化程序复制到聚合中。这意味着您必须具有可访问的复制/移动构造函数。在C ++ 11中,您必须将构造函数参数作为自己的 braced-init-list 传递。这意味着您不是要复制FooC,而是在列表中复制列表初始化FooC,该数组调用2参数构造函数,而不是copy / move构造函数。

FooC array[2] = {
   {1, 2},
   {3, 4}
};

C ++ 17:

braced-init-list 中不再有临时对象,并且数组的每个元素都将直接初始化,而不是复制初始化。