为什么在 C++ 中将变量定义和初始化分开?

发布于 2024-10-26 03:29:30 字数 583 浏览 11 评论 0原文

我目前正在研究一些相当古老的 C++ 代码,经常发现类似

int i;
i = 42;

Object* someObject = NULL;
someObject = new Object();

什至

Object someObject;
someObject = getTheObject();

我完全理解这段代码的作用,但我真的不知道这种变量定义和初始化的分离何时会有所帮助。我搜索了一些解释,但最终总是得到成员初始化列表或何时应该定义局部变量的问题。

最后,我不明白为什么有人会故意编写这段代码。它只是将定义和初始化分成两行并产生开销 - 在最后一种情况下,它使用默认构造函数创建一个对象,然后在下一行中销毁它。

我想知道我是否应该简单地将代码更改为

int i = 42;
Object* someObject = new Object();
Object someObject = getTheObject();

这会导致任何问题吗?

I'm currently working on some quite old C++ code and often find things like

int i;
i = 42;

or

Object* someObject = NULL;
someObject = new Object();

or even

Object someObject;
someObject = getTheObject();

I completely understand what this code does but I really have no idea when such a separation of variable definition and initialization could be helpful. I searched for some explanations but always ended up with member initialization lists or the question when you should define your local variables.

In the end, I don't understand the reason why someone could have intentionally written this code. It just splits definition and initialization up into two subsequent lines and creates overhead – in the last case it creates an object using the default constructor only to destroy it in the next line.

I wonder whether I should simply change the code to

int i = 42;
Object* someObject = new Object();
Object someObject = getTheObject();

Could this lead to any problems?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

执手闯天涯 2024-11-02 03:29:42
int i;
i = 42;

这不是单独的变量定义和初始化。初始化

这是单独的变量声明和赋值。我看不出有什么理由。如果您在声明变量时知道该值,则立即对其进行初始化。所以你的问题没有任何合理的解释。

当然,如果你不知道声明时的值,那么你就没有任何选择,你需要赋值

int i;
i = 42;

That is not separate variable definition and initialization.

That is separate variable declaration and assignment. I don't see any reason for this. If you know the value at the time of declaration of variable, then initialize it right then. So your question doesn't has any rationale explanation.

Of course, if you don't know the value at the time of declaration, then you don't have any choice, you need assignment then.

青衫负雪 2024-11-02 03:29:42

不,这是风格问题。

然而,如果他想将声明移出函数,那么如果声明和初始化是分开的,那么编辑就会减少。

No. It's a matter of style.

However if he ever wanted to move the declaration out of the function it would be less editing if the declaration and initialization is seperated.

等风来 2024-11-02 03:29:42

拆分版本

int i;
i = 42;

错误:跳转到标签交叉初始化
的解决方法
将代码从 C 移植到 C++ 时,

int main() {
  goto some_label;

  // fix: error: jump to label ‘some_label’ crosses initialization of ‘int x’
  // https://stackoverflow.com/a/24015044/10440128
  //int x = 1;
  int x;
  x = 1;

  some_label:
  return x;
}

带有 int x = 1; 的代码在 C 中工作(int x 初始化为零),但在 C++ 中失败,

我制作了一个 bash 脚本 < a href="https://github.com/milahu/random/blob/master/cpp/refactor-split-declaration-and-initialization/c2cpp-split-declaration-and-initialization.sh" rel="nofollow noreferrer" >c2cpp-split-declaration-and-initialization.sh 来自动执行此重构。理想情况下,这应该使用 clang 重构引擎 来实现

the split version

int i;
i = 42;

is a workaround for error: jump to label crosses initialization
when porting code from C to C++

int main() {
  goto some_label;

  // fix: error: jump to label ‘some_label’ crosses initialization of ‘int x’
  // https://stackoverflow.com/a/24015044/10440128
  //int x = 1;
  int x;
  x = 1;

  some_label:
  return x;
}

the code with int x = 1; works in C (int x is initialized to zero) but fails in C++

i made a bash script c2cpp-split-declaration-and-initialization.sh to automate this refactoring. ideally this should be implemented with the clang refactoring engine

财迷小姐 2024-11-02 03:29:41

强烈建议您提出的更改!这是 C++ 编程中一个重要习惯用法的一部分,即资源获取即初始化

The change you propose is highly recommended! This is part of an important idiom in C++ programming, namely Resource Acquisition Is Initialization.

一花一树开 2024-11-02 03:29:41

基于 ROM 的硬件有一个很好的技术原因,这不是风格问题:

在基于 ROM/EEPROM 的嵌入式系统上,这会影响二进制值写入的位置。未初始化的变量写入.bss,而初始化的变量写入.data。过早的初始化会使您的 ROM 空间膨胀,这在较旧的嵌入式系统上可能会给您带来很大的麻烦。如果您运行的系统具有较小的 ROM,则如果进行不必要的初始化,则可能会耗尽内存。一些愚蠢的编译器甚至会直接寻址到 ROM,如果你不小心的话,这些值实际上是只读的。

例如,请参阅此 GameBoy 示例以获得更全面的解释:
http://www.nongnu.org/avr-libc/user -manual/FAQ.html#faq_varinit

There is a good technical reason on ROM-based hardware, it is NOT a style issue:

On ROM/EEPROM based embedded systems, this has an effect on where in the binary the value is written. Uninitialized variables are written into .bss, whereas initialized variables are written into .data. Premature initialization will bloat your ROM space, which on older embedded systems can get you into big, big trouble. If you are running on a system with a small ROM, you can run out of memory if you initialize needlessly. Some goofy compilers will even address directly into the ROM, making these values effectively read-only if you are not careful.

e.g. See this GameBoy example for a more thorough explanation:
http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_varinit

这个俗人 2024-11-02 03:29:41

考虑以下情况:

SomeType object;
if( whateverCondition ) {
   object = getObjectOneWay();
} else {
   object = getObjectAnotherWay();
}

这样很明显两个分支都分配了变量并且其初始值是无关的。然而,这很少值得。

Consider the following case:

SomeType object;
if( whateverCondition ) {
   object = getObjectOneWay();
} else {
   object = getObjectAnotherWay();
}

this way it's clear that both branches assign the variable and its initial value is irrelevant. It's rarely worth that however.

笑脸一如从前 2024-11-02 03:29:41

为什么在 C++ 中将变量定义和初始化分开?

您还没有分开定义和初始化。您刚刚在代码片段中分配了变量/对象(某些特定的)值。所以标题有误导性。

Object someObject;
someObject = getTheObject();

Object someObject = getTheObject(); 完全不同

someObject = getTheObject(); 调用 Object 类的赋值运算符,而在 Object someObject = getTheObject(); 调用类的复制构造函数。这也称为“复制初始化”。

一个好的编译器可能会在 int i; 的情况下生成相同的代码。 i = 42;int i =42。不会有太多的开销。

顺便说一句,我总是更喜欢 int i = 42 而不是 int i; i=42

Object someObject = getTheObject();

Object someObject;
someObject = getTheObject();

PS:int i = 42 定义并初始化 i,而 int i; i=42 定义 i,然后将 42 赋值给它。

Why separate variable definition and initialization in C++?

You haven't separated definition and initialization. You have just assigned the variable/object (to some particular) value in your code snippet. So the title is misleading.

Object someObject;
someObject = getTheObject();

is quite different from Object someObject = getTheObject();

someObject = getTheObject(); invokes the assignment operator of Object class whereas in Object someObject = getTheObject(); copy constructor of the class gets invoked. This is also known by the name copy initialization

A good compiler might generate the same code in case of int i; i = 42; and int i =42. There won't be much of an overhead.

BTW I always prefer int i = 42 to int i; i=42 and

Object someObject = getTheObject(); to

Object someObject;
someObject = getTheObject();

P.S : int i = 42 defines and initializes i whereas int i; i=42 defines i and then assigns 42 to it.

影子是时光的心 2024-11-02 03:29:40

在非常旧的 C 版本中,有一个限制,即您必须在代码块的顶部定义变量,即使您只在函数的稍后位置需要它们。因此,在 C 的旧时代,人们通常首先定义所有变量,然后再考虑它们应该具有的值。

既然你说它是相当古老的 C++ 代码,它可能会使用相同的约定作为 C 实践的保留。

不过,在 C++ 中没有真正的理由这样做。最好总是在可以直接初始化变量的地方定义变量。

In very old versions of C, there was the restriction that you have to define your variables at the top of the code block, even if you only need them somewhere later on in the function. So in the old days of C, people often first defined all their variables and then later thought about the values they should have.

Since you say it is quite old C++ code, it might use that same convention as a holdover from C practices.

There is no real reason to do this in C++, though. Better always define your variables where you can initialize them directly.

独自唱情﹋歌 2024-11-02 03:29:38
Object someObject;
someObject = getTheObject();

这使用了赋值运算符。

Object someObject = getTheObject();

这使用了复制构造函数。

除此之外,您建议的更改是等效的,您应该实施它们。复制构造函数/赋值运算符的差异预期会产生相同的结果,但这并不是由语言强制执行的。

我认为没有像原始代码那样分割声明和赋值的有效理由 - 即使出于所有实际目的,它不会引入开销(对象除外)

Object someObject;
someObject = getTheObject();

This uses the assignment operator.

Object someObject = getTheObject();

This uses the copy constructor.

Apart from that, your suggested changes are equivalent, and you should implement them. The copy ctor/assignment operator difference is expected to produce the same result, this is not enforced by the language though.

I see no valid reason to split up declaration and assignment like the original code does - even though for all practical purposes it doesn't introduce overhead (except for the object)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文