Xeo*_*Xeo 20 c++ initialization visual-c++ c++11
以下代码在标记的行上触发C4345:
#include <array>
#include <iostream>
int main(){
static unsigned const buf_size = 5;
typedef std::array<char, buf_size> buf_type;
char buf[] = { 5, 5, 5, 5, 5 };
void* p = &buf[0];
buf_type* pbuf = new (p) buf_type(); // <=== #10
for(unsigned i=0; i < buf_size; ++i)
std::cout << (char)((*pbuf)[i] + 0x30) << ' ';
}
Run Code Online (Sandbox Code Playgroud)
main.cpp(10):警告C4345:行为改变:使用form()的初始化程序构造的POD类型的对象将被默认初始化
因此,根据他们的警告,第10行应该具有与写入时相同的行为
buf_type* pbuf = new (p) buf_type; // note the missing '()'
Run Code Online (Sandbox Code Playgroud)
但是,输出不同.即,第一个版本将打印五秒0,而第二个版本将打印五秒5.因此,第一个版本确实是值初始化的(并且底层缓冲区零初始化),即使MSVC说它不会.
这可以被视为MSVC中的错误吗?或者我误解了警告/我的测试代码是否有问题?
Ben*_*igt 13
TL; DR版本:MSVC的行为实际上是正确的,虽然警告不正确(应该说值初始化).
因为new (p) buf_type;,MSVC执行默认初始化是正确的,因为标准(5.3.4 [expr.new])要求:
甲新表达式创建类型的对象
T如下初始化该对象:
- 如果省略new-initializer,则默认初始化对象(8.5); 如果没有执行初始化,则该对象具有不确定的值.
- 否则,根据8.5的初始化规则解释new-initializer以进行直接初始化.
std::array是一种类型.对于类类型(8.5 [dcl.init]):
到默认初始化的类型的对象
T是指:
- 如果
T是(可能是cv限定的)类类型,T则调用默认构造函数(如果T没有可访问的默认构造函数,则初始化是错误的);
default-initialization只为原始类型(及其原始数组)保留内存
另一方面,std::array有一个默认的默认构造函数,因此成员本身应该默认初始化.事实上,你观察到了这一点.
然后根据同一部分,该new (p) buf_type();版本导致直接初始化.
std::array是一个聚合,所以我认为这条规则(8.5.1 [dcl.init.aggr])适用:
如果列表中的initializer-clause少于聚合中的成员,则未显式初始化的每个成员都应从空的初始化列表(8.5.4)初始化.
这意味着所有元素的值初始化.
不,这是规则(8.5 [dcl.init]):
初始化器为空的括号集的对象,即
(),应进行值初始化.
聚合的值初始化意味着所有元素的值初始化,因为元素是原始的,这意味着零填充.
所以MSVC的行为实际上是正确的,虽然警告是不正确的(它应该说值初始化).
已有报道,请参阅
| 归档时间: |
|
| 查看次数: |
4367 次 |
| 最近记录: |