在“for”循环中,“int i = 0”和“int i(0)”有什么区别?(对计数变量的赋值与初始化)

13

我在教科书和论坛上看到很多人在for循环中使用赋值操作符而不是初始化操作符来开始重复执行。例如,

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

我知道初始化变量比赋值快。为什么人们更喜欢前者而不是后者?


24
我知道声明变量比对其进行赋值更快。什么?这两种方式都是变量初始化,第一种不是赋值。 - πάντα ῥεῖ
8
那不是赋值运算符。:) int i = 0 是初始化(尽管使用了 =),而 i = 0 才是赋值。当你在同一行声明变量时,它是初始化,而不是赋值。 - jalf
13
即将登陆您附近的电影院:"for (int i{0}; i < 5; ++i)"。该语句为C++编程语言中的循环结构,意为执行一段代码5次。 - Michael Gazonda
6
你混淆了两个概念。你似乎认为“T u = v;”和“u = v;”(或“T u; u=v;”)是一样的,但它们并不相同。因此,你所问的问题基本前提是错误的,因为你写的这两个版本是相同的,正如已经解释过的那样。 - luk32
5
请注意,像image1(image2)这样的结构在不同的上下文中可能具有不同的含义。它可以是一个函数调用或一个构造函数。你的例子看起来像是一个函数调用和赋值运算符。如果你在前面加上类型(T image(image2);T image = image2;),它们都会变成复制构造函数(当然,前提是两个图像都是相同类型的T)。 - luk32
显示剩余4条评论
4个回答

28

在C++中,int i = 0;int i(0);都可以声明、定义和初始化一个值为0的整数对象。它们是完全等价的,两种循环结构也是如此。请注意,在C语言中,int i(0);不是一种合法的结构。


4
并不是所有人都这样做。那些在学习 C++ 之前已经掌握了 C 语言的人可能会因为熟悉程度更高而更喜欢使用前者。 - Mike Seymour
3
在这种情况下,它们没有优势。有时它们会更好。有关更多详细信息,请参见此处 - Baum mit Augen
2
@AerofoilKite 或许第一个版本更符合习惯用法,因为它更接近于 C89 的 for 循环语句 for (i = 0; i < 5; ++i) - ouah
3
对于像这样的简单类型,花括号初始化与其他样式相当,并且没有特别偏好任何一种。它有各种用途,包括避免“最棘手解析”(例如,int i();不声明变量,但是int i{};会),以及对于std :: vector等类来允许从元素列表进行初始化。 - Mike Seymour
2
@MikeSeymour:那么你认为C++03的foo<3 > 2>是最令人困惑的解析的一个例子吗? - Lightness Races in Orbit
显示剩余10条评论

9

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

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

_1

这可能涉及到两个调用。一个是转换构造函数,另一个是复制构造函数。虽然大多数编译器可以省略复制构造。

_2

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

因此,_2比_1更好。对于内置类型,不会有太大的区别。


2
为什么这个答案被点赞了?如果有一个支持 T t(u); 的构造函数,在这种情况下,T t=u; 不会涉及到两次调用。它将调用构造函数或复制构造函数之一。否则,请提供一个示例,我将撤销投票。我刚试过了gcc。 - kiranpradeep
1
如果没有编译器,那么这种答案应该通过参考标准来支持。同时请注意,“内置类型不会有太大的区别”这一引用并不是有益的,可能会让提问者感到困惑。如果语句_1是真的,那么对于内置类型,将调用两个构造函数,这本身就会产生一些微小的差异。 - kiranpradeep
4
如果禁用复制省略,任何编译器都可能调用 _1 的复制构造函数。如果选择省略复制,则可能不会调用该函数,因为这是允许优化的情况之一(从相同类型的临时对象初始化对象)。在 _2 中进行直接初始化不会调用复制构造函数。答案对于类类型是正确的;正如它所说,对于简单类型来说几乎没有区别。 - Mike Seymour
4
如果复制构造函数是私有的,g++ 4.8.3不能编译第一个例子,但可以编译第二个例子。(这看起来是正确的行为,但我没有阅读标准-VS2013可以编译两种情况)。我认为这比轻微的可能性能差异更重要。 - Voo
1
@MikeSeymour。谢谢。我之前不知道复制省略,只是尝试了-fno-elide-constructors标志,这会调用两个构造函数。 - kiranpradeep
显示剩余10条评论

1

你也可以这样写:

int i(5);

或者

int i{5};

或者

int i=5;

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

5
它们中没有一个是作业。 - Lightness Races in Orbit

0
在C编程语言中,你必须先定义变量,然后再进行初始化。要执行for循环,需要在函数开始时定义变量,然后才能写for( i=0 ; i<5 ; ++i )。因此,经常使用这种语言的人可能不习惯这种类型的赋值,在C++中也可能如此,或者只是不想让初学者读者感到困惑。
然而,在C++中,使用for( int i=0 ; i<5 ; ++i )for ( int i(0); i < 5; ++i )是一样的,因为在两种情况下,变量都是在循环的第一次迭代之前创建的。

如果你写 int i; for(i=0 ; i<5 ; ++i ); 它也会在第一个循环之前被创建,但是它是不同的。这两个版本之所以相同是因为标准规定 int i = 0;int i(0); 是复制构造函数的等效调用。 - luk32
这一切都是正确的,严格来说,但是你对问题的应用并不完全正确。这两个结构之所以相同,是因为它们是相同的,而不是因为它们是在_loop_的第一个迭代之前创建的。 - Lightness Races in Orbit
3
为了执行一个for循环,在函数开始时需要定义变量,然后才写for( i=0 ; i<5 ; ++i )是明显错误的,除非你是来自上个世纪的时空旅行者。C99允许使用for ( int i=0 ; i<5 ; ++i ),对于任何C程序员来说,这更符合习惯用法。 - user2005819

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接