在c++中使用花括号来隔离我想多次使用的变量

Using curly braces to segregate a variable that I want to use multiple times in C++

本文关键字:变量 隔离 c++      更新时间:2023-10-16

在下面的代码中,我有一个while语句用于确保输入字符串小于10个字符。我已经声明了一个叫做contbool,我用它来告诉while循环在我的条件满足后停止。

#include "stdafx.h"
#include <iostream>
#include <string>
int main()
{
    using namespace std;
    cout << "Enter a string less than 10 characters long: ";
    string teststring;
    {
        bool cont(false);
        //if input is 10 or more characters, ask for input again until it is less
        while (!cont)
        {
            getline(cin, teststring);
            if (teststring.length() >= 10)
            {
                cout << "Too long, try again: ";
            }
            else
            {
                cout << "Thank you.nn";
                cont = true;
            }
        }
    }
    return 0;
}

正如您在那里看到的,我使用了一组{} s来分离代码,在这些大括号内给cont变量一个局部作用域。我这样做是为了,如果我想再次使用那个变量名,我可以重新声明它,当我用完它的时候,它就被销毁了。

这是可以接受的做法吗?或者有更好的方法来完成我所做的?我承认,在这个特定的基本场景中,条件非常简单,几乎没有必要,但我可能希望将来在更复杂的循环中这样做。

总的来说?是的。这很好。

在这种特殊情况下?不。不必要的。您没有再次使用这个名称,并且在这个简单的代码中您不会这样做。所以这只是噪音。

See…这是一个平衡。

我发现自己在执行几个相关SQL语句的函数中经常这样做。每次我可能会用std::stringstreamss来构建它。当然,我可以给每个语句构建器起一个不同的名字,但是将每个语句构建器保持在自己的作用域内完全可以防止错误。

这是一种可接受的做法,并且完全符合您的要求。然而,很少使用它,因为在小函数中,cont变量在函数顶层作用域中是明确的,因此是可以接受的。如果你觉得你需要在一个较大的函数中分离作用域,那么用一个显式的名字创建另一个函数通常是最好的。

你可以把这些大括号看作只被调用一次的无名函数。如果你发现自己经常使用它,也许你应该给它起一个自己的名字。

另一个选项是重写循环,使其不需要cont变量,例如:
string teststring;
do
{
    cout << "Enter a string less than 10 characters long: ";
    getline(cin, teststring);
} while (teststring.length() >= 10);
cout << "Thank you.nn";

但这并不总是可能的,特别是如果您需要根据停止条件输出不同的消息

是的,如果您有充分的理由重用一个变量,这很好。锁保护在我自己的代码中是最常见的用法,在Lightness的std::stringstream ss回答中给出了这个例子。基本上,只要选择不同的变量名感觉比较尴尬,就可以这样做。例如,如果你写lock1, lock2, lock3,…

然而,更可接受的做法是将长函数体视为代码气味,并将其重构为自己的函数。例如

...
string teststring;
{
    bool cont(false);
    //10 lines of code to handle the foo scenario
}
{
    bool cont(false);
    //15 lines of code to handle the bar scenario
}
...

这可以通过重构来更好地处理:

...
string teststring;
foo(teststring);
bar(teststring);
...
void foo(string &teststring){
bool cont(false);
//10 lines of code
}
void bar(string &teststring){
bool cont(false);
//15 lines of code
}

这显然是一个玩具案例,但这是一个很好的实践,"独立"块就是为了这个目的而存在的。我相信它们是构建长函数的更好方法,而不是将其分解成(在许多情况下)没有单独用途的成员。

在这种情况下,你可以提供一个更快,更清晰,更安全的程序,特别是如果有一个注释(可能是一行)介绍每个块。

但是在这种情况下你可以考虑:

    for ( bool cont(false);!cont;)

具有相同的效果。在for(.;.;.)语句中声明的变量被限制在该语句的范围内。

在这种情况下,你可以用:

回避整个变量:
    for(;;) //<--- Canonical formulation for 'infinite' loop.
    {
        getline(cin, teststring);
        if (teststring.length() >= 10)
        {
            cout << "Too long, try again: ";
        }
        else
        {
            cout << "Thank you.nn";
            break; //<--- Escapes the loop.
        }
    }

脚注(回应评论):

您应该将for循环视为while循环上的"语法糖"。他们的表现没有什么不同,等等,只要挑一个读起来最好的。for(;cond;)看起来很有趣。

break可能有一个很小(很小)的性能优势,但我碰巧认为它在许多情况下实际上更简单,更可读。

如果代码更复杂,可能会有更多的"循环结束"代码,所以它变成:

for(bool cont(false);!cont;) {
    //Complex code with multiple 'exit' conditions...
    if(!cont) {
        //Go round again code that won't fit nicely in last term of for loop...
    }
}

而使用break只是使"快速退出"更容易理解。他们没有(广泛)被认为有goto的"坏业力",因为他们"去"一个非常明确的执行点。