【问题标题】:How to default-initialize local variables of built-in types in C++?如何在 C++ 中默认初始化内置类型的局部变量?
【发布时间】:2024-05-04 22:35:02
【问题描述】:

如何在 C++ 中默认初始化原始类型的局部变量?例如,如果 a 有 typedef:

typedef unsigned char boolean;//that's Microsoft RPC runtime typedef

我想更改以下行:

boolean variable = 0; //initialize to some value to ensure reproduceable behavior
retrieveValue( &variable ); // do actual job

变成可以自动默认初始化变量的东西——我不需要为它分配一个特定的值,而是我只需要在每次程序运行时将它初始化为相同的值——与带有我可以拥有的构造函数初始化列表:

struct Struct {
   int Value;
   Struct() : Value() {}
};

每次创建实例时,Struct::Value 都会默认初始化为相同的值,但我从不在代码中写入实际值。

我怎样才能使局部变量具有相同的行为?

【问题讨论】:

  • 你想达到什么目的? Mabe 在对象中装箱原始变量会有所帮助吗?
  • @clyfe:我不想在我的代码中包含实际值,因为这无关紧要。
  • 我不确定你到底想要什么。你想自动拥有T obj; default-initialize obj 即使是内置的?那是不可能的。还是您只需要一种方法来默认初始化obj,无论它是什么类型?然后,正如一些答案已经说过的那样,T obj = T(); 是要走的路。
  • 另一方面:boolean variable = retrieveValue() 也不错。这样打字就少了:)
  • 想要将变量初始化为某些东西但不在乎什么似乎很奇怪。我想知道您是否正在尝试在这里解决一些更大的问题,并且可能有更好的方法来解决这个问题?

标签: c++ initialization local-variables built-in-types


【解决方案1】:

您可以通过以下方式模拟该行为:

boolean x = boolean();

或者,更一般地说,

T x = T();

如果存在这样的默认初始化,这将默认初始化x。但是,无论您做什么,只写T x 都无法解决局部变量的问题。

您也可以使用placement-new 来调用“构造函数”,即使对于POD:

T x;
new (&x) T();

请注意,此代码会为非 POD 类型(特别是对于具有非平凡析构函数的类型)产生未定义的行为。为了使这段代码与用户定义的类型一起工作,我们首先需要调用对象的析构函数:

T x;
x.~T();
new (&x) T();

此语法可用于 POD(由 §§5.2.4/12.4.15 保证),因此上述代码可以不加选择地用于 any 类型。

【讨论】:

  • 我想对于 UDT,后者会引发 UB,因为 ctor 不是在原始内存上调用的,而是在已经构造的对象上调用的。
  • @sbi: true:对于 UDT,后者必须首先调用析构函数。我只是在谈论 POD,但我会澄清这一点以防止误解。
  • x.~T(); 确实适用于模板,其中Tint。但是,在 VC9 和 Comeau 上写相同的字面意思 (x~int();) 都会失败。
  • @sbi:GCC 4.4.2 和-pedantic 也是如此。 §5.2 中的语法提到 type-name 在此处有效,这意味着 class-nameenum-nametypedef-name。因此,这里确实不允许使用基本类型——但它们的类型定义
  • 确实,至少VC9接受typedef int T; T x; x.~T();!我觉得这是一个令人讨厌的违规行为。
【解决方案2】:
    int var = int();
    string str = string();
    ...

...或任何你想要的类型名称。

【讨论】:

  • 实际上,这与输入 int var = 0; 没有什么不同。字符串str;
  • @kotlinski:是的,但是是可互换的。它适用于每个类型名,无需更改文字。当然,对于上面这样的代码,这没什么意义。但是,与模板结合使用时会更有意义。
【解决方案3】:

您可以通过重载转换运算符提供一个充当底层类型的包装器。

#include <cassert>

template <class T>
class Type
{
    T t;
public:
    Type(const T& t = T()): t(t) {}
    operator T&() { return t; }
    operator const T&() const { return t; }
};

int main()
{
    Type<unsigned char> some_value;
    assert(some_value == '\0');
}

这对于转换运算符来说应该是一个相当不错的用法。

【讨论】:

    【解决方案4】:

    如您的示例中那样包装在结构(布尔)中并通过公共成员(布尔::值)访问。它可能不是最优雅的解决方案(有点麻烦),但它与您已经展示的类似。

    【讨论】:

      【解决方案5】:

      如果我理解最初的问题,发帖者是说他希望给定类型的变量始终具有相同的初始值,但他不在乎该值是什么,因为他永远不会看它。我说的对吗?

      如果是这样,那么我对海报的问题是:如果您没有初始化变量,它们将具有随机初始值......但您说您从不查看初始值 - 那么它们为什么重要随机?

      我认为关键问题是 - 你想在这里实现什么目标?

      【讨论】:

      • 未初始化的变量可能会引入不可重现的行为。相同的变量在不同的程序运行时可能具有不同的值。那是我不想要的。
      • @joefis:如果您想对问题进行澄清,请使用 cmets,而不是答案。
      • > 在不同的程序运行中,相同的变量可能具有不同的值。好的,但这只有在您访问和使用未初始化变量的值时才有意义,这肯定是一个错误......
      最近更新 更多