C++ 在循环之外声明参数是否更有效;什么范围?
有时,在查看优化的代码时,我会看到仅在循环范围内使用的参数的声明被移到了循环之外 大概是这样的:C++ 在循环之外声明参数是否更有效;什么范围?,c++,optimization,scope,declaration,C++,Optimization,Scope,Declaration,有时,在查看优化的代码时,我会看到仅在循环范围内使用的参数的声明被移到了循环之外 大概是这样的: A arr[BIG_NUMBER]; // .... // for (int i=0; i!=BIG_NUMBER; ++i) { B b = arr[i].getB(); // ... do some work with b. } 变成这样: A arr[BIG_NUMBER]; // .... // B b; for (int i=0; i!=BIG_NUMBER; +
A arr[BIG_NUMBER];
// .... //
for (int i=0; i!=BIG_NUMBER; ++i)
{
B b = arr[i].getB();
// ... do some work with b.
}
变成这样:
A arr[BIG_NUMBER];
// .... //
B b;
for (int i=0; i!=BIG_NUMBER; ++i)
{
b = arr[i].getB();
// ... do some work with b.
}
大概原因是我们在不断地重新定义b
。但这样做合理吗?答案是否因B是基元类型还是类而不同
我认为,虽然for循环中变量的范围限制可能会阻止它们在循环之外被访问,但由于循环的内容存在于同一堆栈框架中,“实际”声明只发生一次
(NB,我已经考虑过了,但是考虑到这是一个不同的问题,因为它与声明相关而不是初始化有关的任何费用)。
编辑-改进的标题如果是原语类型,编译器将相应地进行优化 如果它是用户定义的类,则取决于。什么更昂贵,一个额外的初始化或
BIG_NUMBER
析构函数
比较这些:
B b; //one initialization
for (int i=0; i!=BIG_NUMBER; ++i)
{
b = arr[i].getB(); //BIG_NUMBER assignments
}
for (int i=0; i!=BIG_NUMBER; ++i)
{
B b = arr[i].getB(); //BIG_NUMBER initializations
//should be the same as an assignment
} //BIG_NUMBER objects destroyed
没有一般的答案。这取决于编译器B的类型 您正在使用,并且可能在循环中正在做什么(在 分配)。你所能做的就是测量,即使这样也只能说明问题
您可以了解在一台特定机器上运行的特定编译器 @JoachimPileborg构造函数/析构函数是否昂贵并不重要。编译器还可以选择调整块入口/出口上的堆栈指针(不记得是否可以要求g++这样做,默认情况下不会),尽管与循环构造相比,成本微不足道。注意:额外的作用域可以通过用另一对花括号将所有内容包装起来来抵消<代码>{B;for(…){}是一个可接受的构造,通常用于RAII构造。当对象拥有一些昂贵的构造资源时,它会产生影响,而这些资源不受赋值的影响(因此您应该在循环外进行初始化)。或者当
getB
按值返回时,您会得到一个副本省略,这当然是赋值不可能的(因此您应该在循环内初始化,或者交换而不是赋值)。移动语义主要缓解了后者。