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

Inline use of non-default explicit constructor for a member object

本文关键字:默认 构造函数 成员对象      更新时间:2023-10-16

在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::矢量b(123);

这是clang 3.7版的消息:

错误:需要参数声明符std::矢量b(123);

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

N2756

科纳提出的关于标识符范围的问题:

在2007年9月的核心工作组讨论中在科纳举行的会议上,出现了一个关于初始化器。我们想允许类范围有可能正向查找;还是要求初始化程序在解析时定义明确?

所需内容:

类范围查找的动机是我们希望能够在非静态数据成员的初始值设定项中放入我们可以在不显著更改语义的情况下放入mem初始值设定项(模直接初始化与复制初始化):

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在科纳进行了6比3的民意调查,支持阶级范围查找;这就是本文提出的,使用非静态的初始化器限制为"=初始值设定项子句"answers"初始值设定项列表}"形式。我们相信:

问题1:由于我们没有提出(),因此不会出现此问题符号={}初始值设定项符号不受此影响问题

除非你的编译器不采用复制省略(所有主要的编译器都采用了),否则这种笨拙的初始化方式并没有什么效率低下的地方。问题是C++的语言设计者已经把自己逼到了一个角落。因为初始值设定项列表构造函数是贪婪的,所以大括号初始化将使用给定的元素构造一个向量,而使用括号的旧语法则调用显式构造函数来设置大小。

但你不能在NSDMI中使用那个构造函数。除非你用等号。

如果出于某种原因让你感到困扰,有一些笨拙的解决方法:

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

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

std::vector<char> c;
A() : c(123)
{
}