请考虑以下代码
struct B
{
B() : member{}{};
int member[10];
};
int main()
{
B b;
}
Run Code Online (Sandbox Code Playgroud)
VS2013编译器发出以下警告:
警告C4351:新行为:数组'B :: member'的元素将默认初始化1> test.vcxproj - > C:\ Users\asaxena2\documents\visual studio 2013\Projects\test\Debug\test.exe
使用C++ 11,并应用"默认初始化"的概念,意味着B.member的元素将不会被初始化.
但我相信member{}应该执行值初始化而不是默认初始化.VS2013编译器坏了吗?
$ 7.0/6
默认初始化类型对象
T意味着: - 如果T是(可能是cv限定的)类类型(第9节),T则调用默认构造函数(如果T没有可访问的默认构造函数,则初始化是错误的);
- 如果T是数组类型,则每个元素都是默认初始化的;
- 否则,不执行初始化.
如果程序要求对const-qualified类型的对象进行默认初始化T,则T应该是具有用户提供的默认构造函数的类类型.
$ 8.5.1
对象或类型引用的列表初始化
T定义如下:
- 如果初始化列表没有元素并且T是具有默认构造函数的类类型,则对象是值初始化的.
- 否则,如果T是聚合,则执行聚合初始化(8.5.1).如果列表中的initializer-clause少于聚合中的成员,则未显式初始化的每个成员都应从空的初始化列表(8.5.4)初始化.[ 例如:
Run Code Online (Sandbox Code Playgroud)struct S { int a; …
c++ constructor value-initialization c++11 visual-studio-2013
要初始化类型的对象T,可以执行以下某项操作:
T x = T();
T x((T()));
Run Code Online (Sandbox Code Playgroud)
我的问题涉及由简单类型说明符组合指定的类型,例如unsigned int:
unsigned int x = unsigned int();
unsigned int x((unsigned int()));
Run Code Online (Sandbox Code Playgroud)
Visual C++ 2008和英特尔C++编译器11.1接受这两个没有警告; Comeau 4.3.10.1b2和g ++ 3.4.5(不可否认,并非特别近期)没有.
根据C++标准(C++ 03 5.2.3/2,expr.type.conv):
表达式
T(),其中T是非数组完整对象类型的简单类型说明符(7.1.5.2)或(可能是cv限定的)void类型,创建指定类型的rvalue,它是值初始化的
7.1.5.2说,"简单类型说明符是",并跟随一个包含unsigned和的列表int.
因此,鉴于在5.2.3/2中,"simple-type-specifier"是单数,unsigned并且int是两个类型说明符,上面的例子是否使用unsigned int无效?(如果是这样,后续是,微软和英特尔是否支持所述表达式?)
这个问题更多是出于好奇而不是其他任何问题; 对于由多个简单类型说明符组合指定的所有类型,值初始化等效于零初始化.(这个问题是由回答关于初始化问题的答案的评论提示的).
为什么编译器(clang,gcc)在执行此操作时没有警告缩小转换
float a{3.1231231241234123512354123512341235123541235};
float a = {double(3.1231231241234123512354123512341235123541235)}
Run Code Online (Sandbox Code Playgroud)
我期待一个警告,因为我使用大括号进行显式值初始化.按照这个答案链接它应该吐出一个错误.
通过在这里工作,我认为std::atomic<T> a{}有效的零初始化a.我一直在这么想,并一直在使用它直到这个.在解释我对此的理解之前,我想表明,至少,gcc和clang正在实践中这样做.
#include <cstring>
#include <atomic>
#include <iostream>
int main() {
using atomic = std::atomic<int>;
auto p = (atomic*)operator new(sizeof(atomic));
std::memset(p, -1, sizeof(atomic));
new(p) atomic{};
std::cout << p->load() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
以下是我解释为什么这应该起作用(当然,你可能会这样想).标准说
在以下操作定义中:
- A指的是原子类型之一.
[...]
Run Code Online (Sandbox Code Playgroud)A::A() noexcept = default;效果:使原子对象处于未初始化状态.[注意:这些语义确保与C的兼容性. - 结束语]
它基本上说默认构造函数是微不足道的,什么都不做.我对此很好,但我不知道这是如何使值初始化不适用的.根据cppref,值初始化的影响包括(强调我的):
如果T是一个类型,其默认构造函数既不是用户提供也不是删除(也就是说,它可能是一个具有隐式定义或默认默认构造函数的类),该对象是零初始化的,然后它是默认的 -如果它有一个非平凡的默认构造函数,则初始化;
std::atomic 有一个默认的默认构造函数,所以对象是
点2在这里不适用,因为默认的默认构造函数是微不足道的,但我没有看到任何使得第1点无效的语句.我的理解是正确的还是我错过了什么?
我的问题与Prasoon关于非POD类型和值初始化的问题有关.
我在Ideone和Codepad等在线编译器上尝试了以下代码,但可执行文件在这两个站点上都给出了运行时错误.
#include <iostream>
#include <cassert>
struct Struct {
std::string String;
int Int;
bool k;
};
struct InStruct:Struct
{
InStruct():Struct(){}
};
int main()
{
InStruct i;
assert ( i.Int == 0);
std::cout << "Hello";
}
Run Code Online (Sandbox Code Playgroud)
这是否意味着它们都不支持C++ 03值初始化功能?
我想创建一个包装数字类型的类型(并提供其他功能).
此外,我需要数字和包装器可以隐式地相互转换.
到目前为止,我有:
template<class T>
struct Wrapper
{
T value;
Wrapper() { }
Wrapper(T const &value) : value(value) { }
// ... operators defined here ...
};
Run Code Online (Sandbox Code Playgroud)
这几乎是良好的,但它并不十分具有相同的行为作为内置类型:
#include <iostream>
int main()
{
unsigned int x1, x2 = unsigned int();
Wrapper<unsigned int> y1, y2 = Wrapper<unsigned int>();
std::cerr << x1 << std::endl; // uninitialized, as expected
std::cerr << y1.value << std::endl; // uninitialized, as expected
std::cerr << x2 << std::endl; // zero-initialized, …Run Code Online (Sandbox Code Playgroud) 根据cppreference,没有任何用户提供的构造函数的非联合类类型在构造之前将被初始化为零:
如果T是没有任何用户提供的构造函数的非联合类类型,则该对象被零初始化,然后调用隐式声明的默认构造函数(除非它是微不足道的)
我不确定当使用c ++ 11继承的构造函数时会发生什么,因为引用显式地提到了隐式声明的默认构造函数.
给出以下示例:
#include <iostream>
struct A {
int a;
A() {}
A(int i): a(i) {}
};
struct B: public A {
using A::A;
};
int main() {
B b { 5 };
B* p = new (&b) B{ };
std::cout << b.a << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
什么是正确的输出,0或5?在value-initialization(B{ })之前,是否应该专门提供继承的构造函数的类类型进行零初始化?
考虑结构:
struct mystruct { };
Run Code Online (Sandbox Code Playgroud)
这总是有效的:
constexpr mystruct mystructInstance = mystruct();
Run Code Online (Sandbox Code Playgroud)
即POD的值初始化是constexpr?类似地,如果结构被定义为:
struct mystruct { ~mystruct(); };
Run Code Online (Sandbox Code Playgroud)
最后,这个怎么样:
struct mystruct { mystruct(); ~mystruct(); };
Run Code Online (Sandbox Code Playgroud)
我没有宣布ctr为constexpr,但有没有任何隐含的扣除规则可以保证这一点吗?
零初始化是静态初始化的步骤之一.但你是对的,你不能盲目地替换后者(标签),因为零初始化也是为了初始化值.但是,在C++的上下文中不需要(标记名为)零初始化,因为标记已经存在于静态初始化和值初始化中,并且这些标记更相关.
我认为有一种情况是"零初始化"而不是"静态初始化"或"价值初始化"或"零初始化"永远不会在野外发生,我应该使用更具体的术语如:"静态初始化"或"价值初始化"?
公平地说,我对这些主题的大部分经验都来自于研究这个问题的答案,所以我确定Ben Voigt是对的,我只是想让别人明白为什么.
c++ initialization static-initialization value-initialization
如果我有这样的代码
class Node {
public:
Node *subnodes[10];
};
Node x = Node();
Run Code Online (Sandbox Code Playgroud)
代码运行后是否有保证x->subnodes[0] == nullptr?
我不是 C++ 专家,我发现 C++ 规范令人生畏。这在实践中是可行的,但是规范是否保证在这种情况下将 nullptr 放入数组的每个元素中(而不是说,潜在的垃圾)?到目前为止,我还没有通过找到权威的规范语言来说服自己,并且在野外我看到很多代码示例似乎不相信这是真的。所以,经过一段时间未能想出答案后,我转向你, stack overflow。提前致谢。
c++ ×9
c++11 ×5
arrays ×1
atomic ×1
c++14 ×1
codepad ×1
constexpr ×1
constructor ×1
visual-c++ ×1