有没有什么好的理由在C++中调用默认构造函数时,一组空的圆括号(括号)无效?
MyObject object; // ok - default ctor
MyObject object(blah); // ok
MyObject object(); // error
Run Code Online (Sandbox Code Playgroud)
我似乎每次都自动输入"()".是不是有一个很好的理由不允许这样做?
c++ constructor c++-faq default-constructor most-vexing-parse
的C++ 0x将会使下面的代码和类似代码形成不良的,因为它需要一个所谓的收缩转换的double一个int.
int a[] = { 1.0 };
Run Code Online (Sandbox Code Playgroud)
我想知道这种初始化是否在现实代码中被大量使用.这个改变将破坏多少代码?如果您的代码受到影响,是否需要在代码中修复此问题?
供参考,参见n3225的8.5.4/6
缩小转换是隐式转换
- 从浮点类型到整数类型,或
- 从long double到double或float,或从double到float,除非source是常量表达式,转换后的实际值在可以表示的值范围内(即使它不能精确表示),或者
- 从整数类型或无范围枚举类型到浮点类型,除非源是常量表达式,转换后的实际值将适合目标类型,并在转换回原始类型时生成原始值,或者
- 从整数类型或未范围的枚举类型到不能表示原始类型的所有值的整数类型,除非source是常量表达式,并且转换后的实际值将适合目标类型并且将在生成原始值时生成原始值转换回原始类型.
从C++ 11开始,标准库容器和std::string构造函数都采用初始化列表.这个构造函数优先于其他构造函数(甚至,正如@ JohannesSchaub-litb在评论中指出的那样,甚至忽略了其他"最佳匹配"标准).当将所有带括号()的构造函数转换为其支撑版本时,这会导致一些众所周知的陷阱{}
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
#include <string>
void print(std::vector<int> const& v)
{
std::copy(begin(v), end(v), std::ostream_iterator<int>(std::cout, ","));
std::cout << "\n";
}
void print(std::string const& s)
{
std::cout << s << "\n";
}
int main()
{
// well-known
print(std::vector<int>{ 11, 22 }); // 11, 22, not 11 copies of 22
print(std::vector<int>{ 11 }); // 11, not 11 copies of 0
// more surprising
print(std::string{ 65, 'C' }); // AC, not 65 …Run Code Online (Sandbox Code Playgroud) 在SO上已经有类似的问题,但我想强调braced-init-lists的另一个方面.考虑以下:
auto x = {1}; //(1)
Run Code Online (Sandbox Code Playgroud)
除非<initializer_list>包含标题,否则这是不正确的(8.5.4/2).但为什么?标准说,模板std::initializer_list不是预定义的.这是否意味着,声明(1)引入了一种新类型?在所有其他情况下,auto可以使用的地方如
auto y = expr;
Run Code Online (Sandbox Code Playgroud)
where expr是表达式,auto deduces类型已经存在.另一方面,从逻辑的角度来看,编译器必须为构造分配一个implicite类型{1},std::initializer_list然后是另一个名称.但是在声明(1)中我们不想命名这种类型.那么为什么必须包括这个标题.有类似的情况nullptr.它的类型隐含存在,但要明确指出它必须包括<cstddef>.