c++ - 浮点成员是否保证使用 {} 语法初始化为零?
问题描述
在 C++17 中,考虑这样一种情况,S
即具有已删除默认构造函数和浮点成员的结构,当 S 用空括号初始化时,标准是否保证浮点成员为零初始化?
struct A {
int x{};
};
struct S
{
S() = delete;
A a;
float b;
};
int main()
{
auto s = S{}; // Is s.b guaranteed to be zero?
}
在我看来,cppreference.com 并不清楚,两者都说:
如果初始化子句的数量小于成员数且 basesor 初始化器列表完全为空,则剩余的成员和基 (C++17 起)由其默认成员初始化器初始化,如果在类定义中提供,否则(自 C++14 起)根据通常的列表初始化规则从空列表复制初始化(它使用默认构造函数对非类类型和非聚合类执行值初始化,并对聚合执行聚合初始化)。如果引用类型的成员是这些剩余成员之一,则程序格式错误。
(从这里),这意味着 b 保证为零
在所有情况下,如果使用空的大括号 {} 对并且 T 是聚合类型,则执行聚合初始化而不是值初始化。
(从这里)
这意味着 b 不能保证为零。
还有一个讨论似乎暗示虽然不能保证,但所有已知的编译器无论如何都会进行零初始化:
该标准规定,当类具有用户提供或删除的默认构造函数时,不执行零初始化,即使重载决议未选择该默认构造函数。如果选择了未删除的默认默认构造函数,所有已知的编译器都会执行额外的零初始化。
解决方案
这是在 C++20 中修复的 C++的一个怪癖。同时,您可以添加explicit
到已删除的默认构造函数中以强制结构变为非聚合,并使您的代码有保证的编译错误:
struct A {
int x{};
};
struct S
{
explicit S() = delete;
const A a;
const float b;
};
int main()
{
auto s = S{}; // error: call to deleted constructor of 'S'
}
推荐阅读
- php - How to get values in one column where another column equals a value with SQL, and store into an array in PHP?
- acumatica - 如何使用 Acumatica API 发送电子邮件?
- wordpress - 通过 REST API 设置 WooCommerce 产品密码
- javascript - Javascript - 这两个对象之间有区别吗?
- php - php stdobject - 调用默认函数
- javascript - hasOwnProperty not working in array of objects, combining objects
- r - 如何将日期和时间转换为R中的数值
- ruby-on-rails - Rails 5 - 重定向时保留 :js 格式
- mysql - 如何将 sql server 连接到 app.js 文件?
- c# - 如何使用 Entity Framework .SqlQuery 以便它可以同时被多个客户端使用?