【问题标题】:Zero-reinitializing a struct in C++在 C++ 中对结构进行零重新初始化
【发布时间】:2016-03-30 05:27:40
【问题描述】:

一个 POD struct 可以在 C++11 中按如下方式进行零初始化:

SomeStruct s{};

但是,如果我已经有一个结构实例并且我想将它重新初始化为零,我该怎么办?以下似乎有效:

s = {};

有人可以指出相关的标准吗?我认为这是正在发生的事情:

  1. 创建了一个新的零初始化实例。
  2. 新实例被分配给现有实例,调用隐式赋值运算符。

【问题讨论】:

  • 我不知道标准,但是 - 其中一些可能会被优化掉。事实上,如果你不使用 0,也许 all 这一切都被优化掉了。
  • 那里有一个明确的规则,允许在赋值的右侧使用大括号。你的假设是非常正确的。
  • 没有“重新初始化”之类的东西。你初始化一次。就一次。您正在做的是分配,并且在微妙和不那么微妙的方式上非常不同。
  • @LightnessRacesinOrbit 我想我的意思是“重置”。基本上我想将它设置回与使用= {}; 初始化的对象相同的状态。
  • 另一个问题是填充。零初始化会将填充归零,但复制它不需要赋值。

标签: c++ c++11 struct language-lawyer


【解决方案1】:

您要查找的内容在 [expr.ass] 中

braced-init-list 可能出现在

的右侧
  • 对标量的赋值,在这种情况下,初始化列表最多只能有一个元素。这 x={v} 的含义,其中 T 是表达式 x 的标量类型,是 x=T{v} 的含义。的含义 x={}x=T{}
  • 对类类型对象的赋值,在这种情况下,初始化列表作为参数传递给 重载决议选择的赋值运算符函数 (13.5.3, 13.3)。

所以你的猜测是正确的。编译器可能(可以在 C++17 及更高版本中)能够优化一些东西,但您可以将其视为创建一个零初始化临时并将其传递给 operator=

【讨论】:

    【解决方案2】:

    s = {}; 不安全。

    问题是你希望它变成s = SomeStruct{};。但是,如果soperator= 有另一个重载then that may be preferred by overload resolution

    所以这是一个反模式,真的。正如其他线程所建议的那样,您最好编写一个函数,例如:

    template<typename T> void reset(T &t) { t = T{}; }
    

    我猜你也可以写 s = decltype(s){};,只要 s 不是参考。

    【讨论】:

    • 为什么不明确使用您的hoped 进行解析。 s = SomeStruct{}?这似乎比对reset() 的函数调用更清楚。
    • @LokiAstari 好吧,我们可能与s 的声明相去甚远,因此要检查它是否真的做正确的事情并不容易。如果我们不小心输入了s = SomeOtherStruct{};,那么可能会发生其他奇怪的影响。我尝试使用代码模式来最大限度地减少错误(特别是非明显错误)的可能性。我猜decltype 版本真的是最好的。我觉得那不美观,但也许我需要更新我的审美
    • 我同意你关于SomeOtherStruct{} 的观点。然后它对decltype 更有意义,但看起来仍然很丑(而且美学很重要)。
    猜你喜欢
    • 1970-01-01
    • 2011-09-21
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多