以下代码触发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) << ' ';
}
main.cpp(10): warning C4345: behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized
因此,根据他们的警告,第 10 行应该具有与写为
相同的行为buf_type* pbuf = new (p) buf_type; // note the missing '()'
但是,输出不同。即,第一个版本将打印五个0
,而第二个版本将打印五个5
。因此,第一个版本确实是值初始化的(并且底层缓冲区是零初始化的),尽管 MSVC 说它不会。
这可以被认为是 MSVC 中的错误吗?还是我误解了警告/我的测试代码有问题?
最佳答案
TL;DR 版本:MSVC 的行为实际上是正确的,尽管警告不正确(应该是 value-initialized)。
对于new (p) buf_type;
,MSVC执行默认初始化是正确的,因为标准(5.3.4 [expr.new]
)要求:
A new-expression that creates an object of type
T
initializes that object as follows:
- If the new-initializer is omitted, the object is default-initialized (8.5); if no initialization is performed, the object has indeterminate value.
- Otherwise, the new-initializer is interpreted according to the initialization rules of 8.5 for direct-initialization.
std::array
是一个类类型。对于类类型(8.5 [dcl.init]
):
To default-initialize an object of type
T
means:
- if
T
is a (possibly cv-qualified) class type, the default constructor forT
is called (and the initialization is ill-formed ifT
has no accessible default constructor);
默认初始化仅对原始类型(及其原始数组)保留内存不变
另一方面,std::array
有一个默认的默认构造函数,因此成员本身应该被默认初始化。事实上,你观察到了这一点。
然后根据同一节,new (p) buf_type();
版本导致直接初始化。
<罢工>
std::array
是一个聚合,所以我认为这个规则(8.5.1 [dcl.init.aggr]
)然后适用:
If there are fewer initializer-clauses in the list than there are members in the aggregate, then each member not explicitly initialized shall be initialized from an empty initializer list (8.5.4).
这意味着对所有元素进行值初始化。
不,这是规则(8.5 [dcl.init]
):
An object whose initializer is an empty set of parentheses, i.e.,
()
, shall be value-initialized.
聚合的值初始化意味着所有元素的值初始化,因为元素是原始的,这意味着零填充。
所以 MSVC 的行为实际上是正确的,虽然警告是不正确的(应该说 value-initialized)。
已经举报了,看
关于c++ - Visual Studio的C4345警告错了吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8697105/