问题标签 [value-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.

0 投票
0 回答
85 浏览

c++ - 在不同的 c++11 标准版本中使用删除的默认构造函数初始化类

在副本中,至少我的问题的第1点和第 4点没有答案。他们是最重要的。我可以删除其他点,但我要求不要结束整个问题。

1.在下面的代码中,obj1 是正常创建的。但是,如果我尝试取消注释 obj2 和 obj3 的创建,则编译 (-std=c++11, g++ 4.9.2) 将失败。为什么会这样?我认为无论对象的内存是在堆栈上还是在堆上分配,都应该以相同的方式执行初始化。


2.根据标准,我试图弄清楚这两种行为(obj1-case 或 obj2,obj3-cases)中的哪一种是正确的。在标准中据说(#3242 和 #3337, 8.5.4):

类型 T 的对象或引用的列表初始化定义如下:

— 如果初始值设定项列表没有元素并且 T 是具有默认构造函数的类类型,则对象是值初始化的。

好的。所以我转到值初始化定义(#3242 和#3337, 8.5.0):

如果 T 是没有用户提供的构造函数的(可能是 cv 限定的)非联合类类型,则该对象是零初始化的,并且如果 T 的隐式声明的默认构造函数是非平凡的,则调用该构造函数。

根据 (#3242, 12.1)

如果默认构造函数既不是用户提供也不是删除,并且如果: 。. .

所以删除的默认构造函数是不平凡的,因此,代码C obj1 { }; 应该无法编译。

但根据 (#3337, 12.1)

如果默认构造函数不是用户提供的并且如果: ,则默认构造函数是微不足道的。. .

因此删除默认构造函数是微不足道的代码C obj1 { }; 应该成功编译。

真相在哪里?

3.但还有更多。在下一版本的标准中,据说(# 3367,8.5.4):

类型 T 的对象或引用的列表初始化定义如下:

— 如果 T 是一个聚合,则执行聚合初始化

— 否则,如果初始值设定项列表没有元素并且 T 是具有默认构造函数的类类型,则该对象是值初始化的。

据我了解, C是一个聚合。但是在这里我有一个问题:我找不到如何创建带有已删除的默认构造函数的聚合的信息。8.5.1 Aggregates中没有此类信息。但是按照这个

当聚合由初始化列表初始化时,如 8.5.4 中所指定,初始化列表的元素被视为聚合成员的初始化,按递增的下标或成员顺序。每个成员都是从相应的 initializer-clause 复制初始化的。. . (#3367, 8.5.1)

我可以假设构造函数 [编译器在聚合的情况下生成] 在聚合初始化期间只是被忽略了。所以我可以假设删除的默认构造函数也被简单地忽略了,所以C obj { }; 应该可以成功编译,但对我来说,使用已删除的默认构造函数创建对象很奇怪。尽管如此,如果我理解正确,根据这个版本的标准 obj1-case 是可以的,而 obj2,obj3-cases 无法编译是错误的。我对吗?

4.逻辑问题是,无论如何,我应该依赖哪个标准版本#3242/#3337 或#3367?版本#3367是2012年做的,所以晚于2011年,不知道能不能叫c++11。哪个版本被认为是真正的 c++11 标准?我使用 g++ 4.9.2 编译了上面的代码示例。编译器使用什么标准变体,我怎么知道?因为版本 #3337 或 #3367 差异很大。

例如,在 #3367 中,值初始化的定义发生了巨大变化:

对 T 类型的对象进行值初始化意味着:

— 如果 T 是(可能是 cv 限定的)类类型(第 9 条),没有默认构造函数(12.1)或用户提供或删除的默认构造函数,则对象被默认初始化;

5.在我看来,新的值初始化定义很奇怪,因为我想不出任何情况下我们可以使用已删除的默认构造函数创建和值初始化对象。我的意思是,例如,如果我将C 类的int c成员设为私有,因此 C 类不再是表达式的聚合

将是值初始化(不是以前的聚合初始化)[#3367, 8.5.4 "List-initialization"] 并且肯定无法编译。你能解释一下在新的值初始化定义中删除构造函数的那一刻吗?

我知道这里有很多文字。如果您回答了一些问题,我将非常感激。

0 投票
1 回答
558 浏览

c++ - 聚合初始化之前的 c++11 值初始化

我试图理解@bolov 对已删除默认构造函数问题的第一个接受答案。仍然可以创建对象...有时[1]

好像我在那里发现了一个错误,所以它弄乱了整个解释。

@bolov 解释了为什么此代码成功在 c++11 中编译:

方案 A

以及为什么这段代码无法在 c++11 中编译:

方案 C

他说重点是第一个 foo 是聚合,第二个 foo 不是聚合。

然后他给出了 cppreference 的摘录:

对 T 类型的对象进行列表初始化的效果是: ...

  • 如果 T 是聚合类型,则执行聚合初始化。这需要处理场景 ABDE(和 C++14 中的 F)
  • 否则 T 的构造函数分为两个阶段:

    • 所有采用 std::initializer_list 的构造函数...

    • 否则 [...] T 的所有构造函数都参与重载决议 [...] 这会处理 C(和 C++11 中的 F)...

根据您编写时的摘录foo f { }; 场景 A中,您将获得聚合初始化。那就太好了。但实际上在 c++11(#3337 草案,最接近标准)中,你有不同的初始化顺序

类型 T 的对象或引用的列表初始化定义如下:

  • 如果初始值设定项列表没有元素并且 T 是具有默认构造函数的类类型,则该对象是值初始化的。
  • 否则,如果 T 是一个聚合,则执行聚合初始化 (8.5.1)

所以foo f { }; 场景 A中应该导致值初始化,即会调用 DELETED 默认构造函数,并且代码应该编译失败。

0 投票
1 回答
91 浏览

c++ - 获取默认初始化(非值/零初始化)的 POD 作为右值

是否可以将类型的右值传递Afoo()而不对其进行值初始化?我们必须使用值初始化还是左值?

你可能会问,当它“花费”不超过 10 纳秒时,避免值初始化有什么意义。像这样的情况怎么样:我们正在寻找遗留应用程序中由 valgrind 未初始化的内存访问引起的错误,并且零不被视为应用程序的有效值。值初始化将阻止 valgrind 发现未初始化内存访问的位置。

您可能会说打印未初始化的值是 UB,但我的“真实”用例并不限于打印。没有它,我的问题应该仍然有效。

0 投票
2 回答
1555 浏览

c++ - 用大括号从双精度浮点初始化

为什么编译器(clang,gcc)在执行此操作时不警告缩小转换

我期待一个警告,因为我使用大括号进行显式值初始化。按照这个答案链接它应该吐出一个错误。

在这里编译

0 投票
1 回答
1864 浏览

c++ - C++ 中的对象字面量替代

我来自类似 Javascript 的语言,我可以在其中制作这样的功能。

这像这样使用:

如果不清楚,这会使 mySprite 的 x 和 y 属性在 1 秒内变为 10,循环 5 次,延迟为 1 秒。tweenParams 可以包含 obj 可能具有的任何值,并且 tweenOptions 是一个固定结构。

我想知道这在 C++ 中有多简洁合理,结构和数组初始化似乎不够灵活,无法表达这一点。我最好的猜测涉及一次调用多个补间函数一个属性,例如。

我不太了解 C++ 高级功能,也许运算符重载或自定义初始化可以帮助我?

编辑:要清楚,我不希望它与 Javascript 示例完全匹配,我只想知道这可以合理地简洁。

0 投票
2 回答
151 浏览

c++ - 嵌套类的值初始化

通过值初始化的规则。值初始化发生:

1,5) 当使用由一对空括号或花括号组成的初始化程序创建无名临时对象时 (C++11 起);

2,6) 当具有动态存储持续时间的对象由 new 表达式创建时,初始化器由一对空括号或大括号组成 (C++11 起);

3,7) 当非静态数据成员或基类使用带有一对空括号或大括号的成员初始化程序进行初始化时 (C++11 起);

4) 当一个命名变量(自动的、静态的或线程局部的)用由一对大括号组成的初始化器声明时。

简单的例子

没有显式声明的构造函数并留下默认的默认 ctor // 编译器生成我们得到的一个。

但是使用另一个结构。

ai 的值是零初始化的,即使没有使用 {} / () 构造,这违反了规则(如果我没记错的话)。

在结构 B 上使用相同的逻辑:

我们根据规则获得行为。

最后一个例子:

B().ai 也是零初始化的,而我们显式声明了构造函数并且它没有被删除。

为什么这些值被零初始化?根据此处规定的规则,它们应该是默认初始化而不是零初始化。

感谢您的回答。

0 投票
1 回答
51 浏览

c++ - 安全地依赖 unordered_map (hashmap) 中的初始化值

假设我想构造一个std::unordered_map<char, int>来映射字符串中字符的频率。我会做类似的事情

对我来说,这感觉很危险,因为我怎么知道hashmap[*pch]++会在从 0 开始的 hashmap 条目的值中构造一个整数?我在哪里可以找到此保证(如果存在)?

0 投票
1 回答
937 浏览

c++ - 值初始化是否适用于原子对象?

通过在这里工作,我的意思是std::atomic<T> a{}有效地零初始化a。我一直这么想,并且一直在实际使用它,直到这个。在解释我对此的理解之前,我想表明,至少 gcc 和 clang 在实践中是这样做的。

输出0gccclang上。

以下是我对为什么这应该起作用的解释(当然,您可能会不这么认为)。标准说

在以下操作定义中:

  • A 指的是原子类型之一。

[...]

效果:使原子对象处于未初始化状态。[注意:这些语义确保了与 C 的兼容性。- 尾注]

它基本上说默认构造函数是微不足道的,什么都不做。我对此表示同意,但我不明白这如何使值初始化不适用。根据cppref,值初始化的影响包括(强调我的):

如果 T 是具有既不是用户提供也不是删除的默认构造函数的类类型(即,它可能是具有隐式定义或默认默认构造函数的类),则该对象为零初始化,然后是默认值-如果它具有非平凡的默认构造函数,则初始化;

std::atomic有一个默认的默认构造函数,所以对象是

  1. 零初始化然后
  2. 如果它具有非平凡的默认构造函数,则它是默认初始化的。

第 2 点在这里不适用,因为默认的默认构造函数是微不足道的,但我没有看到任何使第 1 点无效的语句。我的理解是正确的还是我遗漏了什么?

0 投票
2 回答
412 浏览

c++ - C++ 值初始化自定义容器的项

让我们以自定义vector实现为例:

所以我的问题是,如何进行myVector值初始化,以防我将其初始化为:

在这里,它包含 5 个int值,所以我需要它全为零;与其他类型相同。我注释掉了,_buff[i] = 0;因为它是特定于int. 请给我一些提示。

0 投票
2 回答
109 浏览

c++ - 从有符号字符到整数的值初始化,过早提升?

在这段代码中:

应该x-5-261?在我的理解中,初始化表达式是有signed char类型的,类型转换应该在初始化初始化计算之后发生。

所以,v - '0' * (signed char)n应该等于,因为这是估值-5中的等值。-261signed char

但是,那段代码打印-261.