【问题标题】:'int i = 0' vs. 'int i(0)' in a 'for' loop (assigning vs initializing the count variable)“for”循环中的“int i = 0”与“int i(0)”(分配与初始化计数变量)
【发布时间】:2015-01-02 16:45:45
【问题描述】:

我在教科书和论坛中看到很多代码,人们在 for 循环中使用赋值运算符而不是初始化运算符来开始重复。例如,

for ( int i = 0; i < 5; ++i )   // common 
for ( int i(0);  i < 5; ++i ) // uncommon 

我知道初始化一个变量比分配它要快。为什么人们更喜欢前者而不是后者?

【问题讨论】:

  • “我知道初始化一个变量比分配它要快。” 嗯,什么?两种形式都是变量初始化,第一种不是赋值。
  • 这不是赋值运算符。 :) int i = 0 是初始化(尽管使用了=),而i = 0 是赋值。当你在同一行声明变量时,它是初始化,而不是赋值。
  • 即将来到您附近的剧院:for ( int i{0}; i &lt; 5; ++i )
  • @CroCo 你混淆了两件事。您似乎认为T u = v;u = v;(或T u; u=v;)相同,但事实并非如此。你的问题的基本前提是错误的,因为你写的两个版本都是一样的,正如解释的那样。
  • @CroCo 另请注意,image1(image2) 这样的构造可能具有不同的含义,具体取决于上下文。这可以是函数调用,也可以是构造函数。您的示例看起来像函数调用和赋值运算符。而如果你把 type 放在前面(T image(image2);T image = image2;),它们都将成为复制构造函数(假设两个图像的类型相同 T 当然)。

标签: c++


【解决方案1】:

int i = 0;int i(0); 在 C++ 中声明、定义和初始化一个 int 对象,其值为 0。它们是严格等价的,两个循环结构也是如此。请注意,在 C 中,int i(0); 不是允许的构造。

【讨论】:

  • @AerofoilKite:并非所有人都这样做。在 C++ 之前学习 C 的人可能更喜欢前者,因为它熟悉。
  • @Rinzler 在这种情况下他们没有优势。有时他们会更好。有关详细信息,请参阅here
  • @AerofoilKite 可能第一个版本更惯用,因为它更接近 C89 for loop for (i = 0; i &lt; 5; ++i)
  • @Rinzler:对于像这样的简单类型,大括号初始化等价于其他样式,没有特别的理由偏爱其中任何一种。它有多种用途,包括避免“最麻烦的解析”(例如,int i(); 没有声明变量,但 int i{}; 声明了变量),以及像 std::vector 这样的类允许从元素列表进行初始化。跨度>
  • @MikeSeymour: int i(); 不是“最令人头疼的解析”。
【解决方案2】:

你提到的两种初始化形式是:-

T t = u;     _1
T t(u);      _2

_1

可能涉及两个调用。一种是转换构造函数,另一种是复制构造函数。尽管大多数编译器都可以省略复制构造。

_2

这只需要一次调用转换构造函数

因此,_2 优于 _1。至于内置类型,不会有太大区别。

【讨论】:

  • 在实践中,尤其是当uT 时,这些副本将被完全忽略。
  • 为什么这个答案被赞成?如果有一个支持 T t(u); 的构造函数,在这种特殊情况下 T t=u; 不会涉及 2 次调用。它将调用构造函数或复制构造函数。如果不是这样,请发布样本,我将撤销投票。我刚用 gcc 试过
  • 如果没有编译器,那么这种答案应该参考标准来支持。另请注意,对“内置类型不会产生太大影响”的引用没有帮助,并且可能会使 OP 感到困惑。如果语句 _1 为真,那么它将调用两个构造函数,例如对内置类型的调用,并且它本身会产生任何影响,无论多么微小。
  • @Kiran:如果禁用复制省略,任何编译器都可能调用_1 的复制构造函数。如果它选择省略副本,则可能不会,因为这是一种允许优化的情况(从相同类型的临时对象初始化对象)。在_2 中的直接初始化不会调用复制构造函数。答案对于类类型是正确的;而且,正如它所说,普通类型几乎没有区别。
  • 如果复制构造函数是私有的,g++ 4.8.3 不会编译第一个示例,而是第二个示例。 (这似乎是正确的行为,但我没有阅读标准 - VS2013 编译这两种情况)。我会说这是比可能的性能差异更重要的差异。
【解决方案3】:

你可以这样写:

int i(5);

int i{5};

int i=5;

所有这些都是初始化,而不是赋值。 *它们并没有什么不同。

【讨论】:

  • 它们都不是作业。
【解决方案4】:

在 C 编程语言中,您必须先定义变量,然后再对其进行初始化。要执行 for 循环,您需要在函数开头定义变量,然后才编写for( i=0 ; i&lt;5 ; ++i )。因此,经常使用这种语言的人可能不习惯这种类型的作业,可能在 C++ 中,或者只是不想混淆可能的初学者读者。

但是,在 C++ 中,使用 for( int i=0 ; i&lt;5 ; ++i )for ( int i(0); i &lt; 5; ++i ) 是相同的,因为在这两种情况下,变量都是在循环的第一次迭代之前创建的。

【讨论】:

  • 嗯...如果你写int i; for(i=0 ; i&lt;5 ; ++i );,它也会在第一个循环之前创建,但它是不同的。两个提到的版本相同的原因是不同的。之所以如此,是因为标准规定 int i = 0;int i(0); 是复制构造函数的等效调用。
  • 严格来说,这都是正确的,但是您将其应用于问题并不完全正确。这两个构造是相同的,因为它们是相同的,而不是因为它们是在 loop 的第一次迭代之前创建的。
  • "要执行一个 for 循环,你需要在函数的开头定义变量,然后才写for( i=0 ; i&lt;5 ; ++i )"——这显然是错误的,除非你是一个时间旅行者从上个千年开始。 C99 允许 for( int i=0 ; i&lt;5 ; ++i ),这对于任何 C 程序员来说更惯用。
猜你喜欢
  • 2022-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-07
  • 2019-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多