内联使用成员对象的非默认显式构造函数

时间:2016-01-06 03:59:40

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

在C ++ 11(或将来)中,是否有以下简单的变体是合法的?

class A
   {
public:
   std::vector<char> b(123); // declare a vector with 123 elements
   };

我能找到的最近的是有点笨重,也许效率低下......

class A
   {
public:
   std::vector<char> b = std::vector<char>(123);
   };

我正在尝试避免使用初始化列表。我更喜欢将b的声明和初始化合并到一行代码中。矢量将始终具有相同的大小。

我在这个例子中使用std::vector,但可能更普遍适用答案。

为了更好地衡量,这是来自gcc版本4.8的错误消息:

  

错误:数字常量之前的预期标识符       std :: vector b(123);

这是来自clang版本3.7的消息:

  

错误:预期的参数声明符         std :: vector b(123);

1 个答案:

答案 0 :(得分:6)

极不可能。最初允许NSDMI的提案解决了这个问题:

  

N2756

     

Kona就标识符范围提出了一个问题:

     

在2007年9月的核心工作组讨论期间   在科纳举行会议时,出现了一个关于标识符范围的问题   初始化器。我们是否希望允许类范围   正向查找;或者我们是否要求初始化者   在他们被解析的时候明确定义了吗?

     

想要的是什么:

     

类范围查找的动机是我们希望能够   把任何东西都放在我们可以的非静态数据成员的初始化器中   放入mem-initializer而不会显着改变语义   (模数直接初始化与复制初始化):

int x();

struct S {
    int i;
    S() : i(x()) {} // currently well-formed, uses S::x()
    // ...
    static int x();
};

struct T {
    int i = x(); // should use T::x(), ::x() would be a surprise
    // ...
    static int x();
};
     

问题1:

     

不幸的是,这会使“ 表达式列表 ”的初始化程序   在解析声明时表单不明确:

     

...

     

提案:

     

CWG在Kona进行了6比3的民意调查,支持分类范围查询;   这就是本文提出的,非静态的初始化器   数据成员仅限于“ = 初始化条款”和“ {   初始化列表 } “表单。我们相信:

     

问题1 :由于我们不建议(),因此不会出现此问题   符号。 = {} 初始值表示法不会受此影响   问题

除非你的编译器不使用复制省略(并且所有主要的复制省略),否则关于笨重的初始化方式没有任何低效率。问题是C ++的语言设计者已经将自己置于一个角落。因为初始化列表构造函数是 greedy ,所以大括号初始化将构造具有给定元素的向量,而使用括号的较旧语法调用显式构造函数来设置大小。

除非您无法在NSDMI中使用该构造函数。除非你使用等号。

如果由于某种原因困扰你,有一些笨重的解决方法:

std::vector<char> c = decltype(c)(123);
// ...
using VChar = std::vector<char>;
VChar v = VChar(123);

或者意识到新功能并不排除现有功能:

std::vector<char> c;

A() : c(123)
{
}