问题标签 [list-initialization]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - Why doesn't C++11 curly brace initialzation in constructor initialization list work when parens initializaton does?
How is {} initialization in a constructor initialization list different from () initialization when initializing reference to abstract types? Take class Bar below:
When compiling, I get the error
Changing the line
it compiles and runs fine.
Reading through Stroustrup's C++11 book, I was under the impression that {} was the same as () in most all cases, except where there was an ambiguity between constructors that take std::initializer_list<> and other constructors, and cases where using auto as the type, neither of which I'm doing here.
c++ - 为什么 Foo({}) 调用 Foo(0) 而不是 Foo()?
clang 3.5.0 和 gcc 4.9.1 从代码中生成的可执行文件
表现如评论。
来自cppreference:cpp/language/list 初始化:
T 类型对象的列表初始化的效果是:
如果
T
是聚合类型,则执行聚合初始化。否则,如果括号初始化列表为空并且
T
是具有默认构造函数的类类型,则执行值初始化。
我的结论是Foo({})
应该调用默认构造函数。
错误在哪里?
c++ - 为什么大括号初始化列表在函数调用和构造函数调用中的行为不同?
使用 clang 3.5.0 和 gcc 4.9.1 编译以下代码会在最后一条语句中产生错误。
为什么Foo({1, 2})
可以而bar({1, 2})
不行?
特别是,了解基本原理会很棒。
c++ - 复制列表初始化是否在概念上调用复制ctor?
A a = 1;
在 C++11 之前,我们可以通过编写类似于A a = A(1);
. 也就是说,首先创建一个临时对象,然后调用一个复制 ctor。无论复制省略如何,这在概念上都必须如此,并且复制 ctor 必须是可访问的。
使用 C++11 中的列表初始化,我们可以通过编写A a = {1, 2};
. 在我看来,这应该或多或少等同于A a = A(1, 2);
. 但是,在 GCC 和 clang 上,A a = {1, 2}
即使复制和移动 ctor 不可访问(通过声明为私有)也可以编译。尽管如此,A a = 1;
如果相应的复制/移动 ctor 不可访问,则不会在 GCC 或 clang 上编译。因此,A a = {1, 2};
似乎或多或少等同于A a{1, 2};
直接列表初始化。这与真正的直接列表初始化之间的区别在于,A a = {1, 2};
如果采用两个 int 的 ctor 是显式的,则不会编译。在这方面,A a = {1, 2};
类似于复制初始化。
所以,我的问题是:A a = {1, 2};
概念上的表达式的确切语义是什么?从概念上讲,复制省略不会妨碍您。
c++ - 在列表初始化中缩小转换为 bool - 奇怪的行为
考虑这段 C++11 代码:
在x
. 根据我对标准的理解,这是格式错误的代码,我们应该看到一些诊断。
Visual C++ 2013 发出错误:
但是,Clang 3.5.0 和 GCC 4.9.1 都使用以下选项
编译这段代码没有错误和警告。运行程序会输出 a 1
(这并不奇怪)。
现在,让我们深入到陌生的领域。
更改X(bool arg)
为X(int arg)
,突然,我们收到了来自 Clang 的错误
和来自 GCC 的警告
这看起来更像我的预期。
现在,保留bool
构造函数参数(即恢复为X(bool arg)
),并更改double d = 7.0;
为int d = 7;
. 再次,来自 Clang 的缩小错误,但 GCC 根本不发出任何诊断并编译代码。
如果我们将常量直接传递给构造函数,我们可以获得更多的行为变体,有些奇怪,有些是预期的,但我不会在这里列出它们 - 这个问题已经变得太长了。
我想说这是在标准一致性方面 VC++ 正确而 Clang 和 GCC 错误的罕见情况之一,但是,鉴于这些编译器各自的跟踪记录,我对此仍然非常犹豫。
专家们怎么看?
标准参考(引自 C++11 的最终标准文档,ISO/IEC 14882-2011):
在 8.5.4 [dcl.init.list] 第 3 段中,我们有:
— 否则,如果 T 是类类型,则考虑构造函数。枚举适用的构造函数,并通过重载决议(13.3、13.3.1.7)选择最佳构造函数。如果需要缩小转换(见下文)来转换任何参数,则程序格式错误。
在同一部分的第 7 段中,我们有:
缩小转换是一种隐式转换
——从浮点类型到整数类型,或者
——从 long double 到 double 或 float,或者从 double 到 float,除非源是常量表达式并且转换后的实际值是在可以表示的值范围内(即使不能精确表示),或者
——从整数类型或无作用域枚举类型到浮点类型,除非源是常量表达式和转换后的实际值将适合目标类型并在转换回原始类型时生成原始值,或者
— 从整数类型或无作用域枚举类型到不能表示原始类型的所有值的整数类型,除非源是常量表达式并且转换后的实际值将适合目标类型并生成原始值当转换回原始类型时。
[注意:如上所述,列表初始化中的顶级不允许此类转换。-结束注释]
在 3.9.1 [basic.fundamental] 第 7 段中,我们有:
bool、char、char16_t、char32_t、wchar_t 类型以及有符号和无符号整数类型统称为整数类型。48 整数类型的同义词是整数类型。
(在这个阶段我开始质疑一切......)
c++ - 我应该如何大括号初始化 std::pairs 的 std::array?
VS2013 错误:
错误 C2440:“正在初始化”:无法从“int”转换为“std::pair”没有构造函数可以采用源类型,或者构造函数重载决议不明确`
我究竟做错了什么?
c++ - What is the difference between these two forms of list initialization for std::map?
I have tested the following two forms with clang and they are both accepted:
On Visual Studio 2013, the latter example fails to compile stating there is no constructor in map that takes 4 arguments.
I'm assuming both are actually valid. What is the difference between the two? Why doesn't the second example work on Visual Studio 2013?
c++ - 新 struct{} 的列表初始化是否使用变量编译器特定?
使用 Visual Studio 2013 和 C++ 编译器编写另一个链表,并在此过程中反复试验。这是特定于 Visual C++ 还是标准的一部分?
我真的很喜欢这种语法。它超级干净。如果您在不知不觉中编写了一个链表库,您可以四处寻找指针,直到您的大脑陷入困境。这个语法虽然很清楚。
很多这些东西都有静态初始化值,但是使用函数 args 作为初始化?还没有看到那个。
很高兴知道GCC C/C++ 编译器是否产生了预期的结果。任何人?
c++ - initializer_list 构造函数的列表初始化和重载解析失败
以下无法编译clang35 -std=c++11
:
有错误
OTOH,它警告缩小并编译g++48 -std=c++11
并产生结果
这两种行为都有意义吗?引用cppreference
所有将 std::initializer_list 作为唯一参数或作为第一个参数(如果其余参数具有默认值)的构造函数都将被检查,并通过重载决议与 std::initializer_list 类型的单个参数进行匹配
如果前一阶段没有产生匹配,则 T 的所有构造函数都参与重载决议,以对抗由括号初始化列表的元素组成的参数集,并限制只允许非缩小转换。如果此阶段生成显式构造函数作为复制列表初始化的最佳匹配,则编译失败(注意,在简单复制初始化中,根本不考虑显式构造函数)
由于不允许缩小转换,我希望重载解析步骤与构造函数不匹配A(std::initializer_list<int>)
,而是与构造函数匹配A(int, double)
。例如,更改A(std::initializer_list<int>)
为同时使用and和 print进行A(std::initializer_list<std::string>)
编译clang35
g++48
正如预期的那样。
c++ - 为什么这个 initializer_list 构造函数是一个可行的重载?
(这个问题是对此的后续。)
上面的程序无法编译clang35 -std=c++11
whileg++48 -std=c++11
选择一个产生警告来诊断畸形变窄
并产生结果
我的问题是是否A::A(std::initializer_list<int>)
应该是一个可行的超载。以下是我认为暗示initializer_list
过载不可行的标准报价。
从13.3.2 [over.match.viable]
其次,为了
F
成为一个可行的函数,每个参数都应该存在一个隐式转换序列,该序列将该参数转换为 的相应参数F
。
从4 [conv]
当且仅当声明;时,表达式
e
才能隐式转换为类型 对于某些发明的临时变量,格式正确。T
T t=e
t
从8.5.1 [dcl.init.aggr]
如果初始化子句是一个表达式并且需要一个窄化转换来转换该表达式,那么程序是非良构的。
使用8.5.1
and 4
,因为下面的格式不正确
{1, 1.0}
不能隐式转换为std::initializer_list<int>
.
使用来自 的引用,难道13.3.2
不应该暗示A::A(std::initializer_list<int>)
在为 A a1 = {1, 1.0};
找不到可行initializer_list
的构造函数,这句话不应该选择A::A(int, double)
吗?