花括号在C++中用于注释目的,会减慢代码吗?

6
花括号作用域是否会增加代码执行时间? 在我看来,的确会。因为在C++中退出花括号作用域意味着堆栈展开,而为注释而使用花括号作用域会增加堆栈展开次数。但我不知道这是否昂贵?我能忽略这个副作用吗?

对于以下代码片段,您应该关注代码结构而不是代码本身。

#include <iostream>
#include <utility>
#include <vector>
#include <string>

int main()
{
    std::string str = "Hello";
    std::vector<std::string> v;

    {// uses the push_back(const T&) overload, which means 
     // we'll incur the cost of copying str
        v.push_back(str);
        std::cout << "After copy, str is \"" << str << "\"\n";

        //other code involves local variable
     }

    {// uses the rvalue reference push_back(T&&) overload, 
     // which means no strings will be copied; instead, the contents
     // of str will be moved into the vector.  This is less
     // expensive, but also means str might now be empty.
        v.push_back(std::move(str));
        std::cout << "After move, str is \"" << str << "\"\n";

        //other code involves local variable
   }

    std::cout << "The contents of the vector are \"" << v[0]
                                     << "\", \"" << v[1] << "\"\n";
}

5
如果没有需要解开的内容怎么办?无论如何,堆栈解开最终都会发生。 - tkausl
3
看看编译后的汇编代码,自己就能明白了。当大括号不影响你所写的内容时,什么也不会改变。 - Passer By
2
确定的方法是检查汇编输出(或者阅读和理解编译器源代码,但这更难)。在这里快速检查,即使使用-O0,GCC输出的指令数量似乎与是否使用作用域保护一样(我没有检查它们是否是相同的指令,但我期望是);在-O3下,如果它不能优化掉,我会感到震惊。 - Daniel H
作为一个不相关的注释,在大多数现代标准库中,在这种特殊情况下,两个字符串构造函数可能做相同的事情,因为有短字符串优化。 - Daniel H
1
大括号的作用范围是否增加了代码执行时间?在我看来,是的。- 当你可以测量时间时,为什么要有意见呢? - Christian Hackl
谢谢大家的回答。虽然这对我来说是一项非常棘手的工作,但我会尽快通过代码执行时间和汇编语言代码进行测量。然后我会展示结果。 - waterd
4个回答

4

退出作用域会销毁该作用域中声明的所有局部变量(最新的先)。在您的示例中,未在作用域内声明任何局部变量,因此不应该有额外开销。您可以通过将代码编译为汇编语言(在gcc下使用-s),并比较有和没有大括号的结果来确认这一点。


2
现代编译器非常智能,当没有需要时它们不会做任何工作。当您的程序没有利用花括号创建的嵌套作用域时,因为它没有在该作用域中声明任何新变量,编译器不会插入任何额外的代码来处理新作用域。此外,将具有微不足道析构函数的局部变量引入到嵌套作用域中也不会有任何惩罚。总的来说,添加嵌套作用域可能会改变要完成的工作的时间,但总工作量仍将保持不变。
然而,添加不必要的作用域可能会降低代码的可读性。在这种情况下,可读性是严格主观的,因此如果您喜欢额外的“作用域”,则可以免费使用。

2
相反地:额外的作用域可以加快速度。(然而,效果非常微小,你不必费心!)
你知道,在函数内部,编译器对函数使用的所有变量都有完全控制。它不会将一些额外的变量推到你声明它们的堆栈上,并在它们超出作用域时弹出。相反,它将创建一个足够容纳你所需的所有本地变量的堆栈帧。你的编译器通常足够聪明,可以在这个堆栈帧中重复使用空间:当一个int在另一个int被声明之前超出作用域时,第二个int可以重用第一个int在堆栈帧中的位置。
因此,当你减少本地变量的作用域时,你允许编译器在堆栈帧中重复使用更多的位置。这减少了堆栈的总体大小以及堆栈增长/收缩的距离。这反过来又导致更好的缓存使用,从而提高了性能。
尽管如此,这种影响的作用很小,所以你通常应该忽略它,只写最易读懂的代码。

1

花括号用于注释目的会增加堆栈展开次数

不,不会。它们影响局部变量的生命周期,但不影响它们被销毁的次数。

假设您有一个更多的 std::string 对象要插入到 std::vector 中。无论是将其放置在 main 块中还是在额外的花括号块中,它都只会被销毁一次。只是它的生命周期受到影响。在第一种情况下,它比第二种情况下要长。


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