内联使用成员对象的非默认显式构造函数
Posted
技术标签:
【中文标题】内联使用成员对象的非默认显式构造函数【英文标题】:Inline use of non-default explicit constructor for a member object 【发布时间】:2016-01-06 03:59:40 【问题描述】:在 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 版的错误消息:
错误:数字常量之前的预期标识符 标准::向量 b(123);
这是来自clang
3.7 版的消息:
错误:预期的参数声明符 标准::向量 b(123);
【问题讨论】:
std::vector<char> b = decltype(b)(123);
不那么笨重了吗?
@RSahu:我喜欢这样。这是一种改进——减少了冗余。
您可以期待现代编译器的省略 - 有关概述,请参阅 copy_elision
on cpprefrence。
“向量的大小始终相同。” - 如果您没有其他理由特别想要vector
,可以考虑std::array<char, 123> b;
。
@nobar 如果您不能信任基本省略,那么为什么要相信 int x = 1+1;
不会向 google 发送网络请求以仔细检查数学? (根据标准,这是可选的——即允许的)。一个糟糕的编译器会主动生成糟糕的代码,比如在简单的情况下无法省略,这是一个偏执的问题。我知道完全零个无法忽略的 C++11 编译器(除非疯狂的编译器设置)
【参考方案1】:
极不可能。最初允许 NSDMI 的提案首先解决了这个问题:
N2756
在 Kona 中提出的关于标识符范围的问题:
在 07 年 9 月核心工作组的讨论中 在 Kona 的会议上,出现了一个关于标识符的范围的问题 初始化器。我们是否希望允许类范围有可能 正向查找;还是我们想要要求初始化器是 在解析它们时定义明确?
想要什么:
类范围查找的动机是我们希望能够 在非静态数据成员的初始化器中放入任何我们可以使用的东西 在不显着改变语义的情况下放入 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(); ;
问题一:
不幸的是,这使得“( expression-list )”的初始化器 在解析声明时形成歧义:
...
提案:
CWG 在 Kona 进行了 6 比 3 的投票,支持类范围查找; 这就是本文的建议,使用非静态初始化器 数据成员限于“= initializer-clause”和“ initializer-list ”表单。我们相信:
问题 1:这个问题不会发生,因为我们没有提出 () 符号。 = 和 初始值设定项符号不受此影响 问题。
除非您的编译器不使用复制省略(所有主要的编译器都使用),否则这种笨拙的初始化方式并没有什么低效的地方。问题是 C++ 的语言设计者已经把自己逼到了一个角落。因为初始化列表构造函数是 greedy,大括号初始化将构造一个带有给定 elements 的向量,而使用括号的旧语法调用显式构造函数来设置大小。
除非您不能在 NSDMI 中使用该构造函数。除非你使用等号。
如果由于某种原因让您感到困扰,有一些笨拙的解决方法:
std::vector<char> c = decltype(c)(123);
// ...
using VChar = std::vector<char>;
VChar v = VChar(123);
或者意识到新功能并不排除现有功能:
std::vector<char> c;
A() : c(123)
【讨论】:
以上是关于内联使用成员对象的非默认显式构造函数的主要内容,如果未能解决你的问题,请参考以下文章