【问题标题】:Using curly braces to segregate a variable that I want to use multiple times in C++使用花括号分隔我想在 C++ 中多次使用的变量
【发布时间】:2015-08-10 12:48:39
【问题描述】:

在下面的代码中,我有一个 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.\n\n";
                cont = true;
            }

        }
    }

    return 0;
}

如您所见,我使用了一组{}s 将代码分开,在这些大括号内为cont 变量提供了一个局部范围。我这样做是为了如果我想再次使用那个变量名,我可以重新声明它,当我用完它时,它就被销毁了。

这是一种可接受的做法吗?还是有更好的方法来做我所做的事情?我承认,在这个特定的基本场景中,条件很简单,几乎没有必要,但我可能希望在未来更复杂的循环中这样做。

【问题讨论】:

  • 如果要再次使用它,为什么要重新声明它?您可以在循环之后将其设置为 false 并根据需要重用它(没有范围的东西)
  • 如果您发现自己需要这样做,那么您在一个函数中的代码太多了。你应该把它分解成一个单独的函数。
  • @T.C.我不确定这是否具有您认为的效果。 ideone.com/qt3D8h
  • @DanAllen 好点。实际上,它每次迭代都会创建一个新变量(并重新初始化它),这与for 不同,因此可能会使用while(bool b = some_function()) { /* run until some_function returns false */ }
  • @T.C 改变了一切!幸运的是,我还听到了其他一些不错的建议,所以我现在当然有选择了!

标签: c++ loops while-loop curly-braces


【解决方案1】:

一般?是的。这很好。

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

看……这是一种平衡。

我发现自己在执行多个相关 SQL 语句的函数中经常这样做。每次我都可以用一个名为ssstd::stringstream 来构建它。当然,我可以给每个语句一个不同的名称,但它完全可以防止错误,将每个语句生成器保持在自己的范围内。

当你使用像锁守卫这样的东西时,这也是一种非常常见的技术。

【讨论】:

  • 同意在这种情况下没有意义。我想我的意思是如果我有多个循环,每个循环都做不同的事情,所以我不能只做一个中性函数。但是有人提到我可以在条件中声明bool,这可能更有意义。不过谢谢!
【解决方案2】:

这是一种可以接受的做法,并且完全按照您所说的去做。然而,它很少使用,因为在小型函数中,它是明确的,因此在函数顶级范围内具有 cont 变量是可以接受的。如果您觉得需要在更大的函数中分离作用域,通常首选创建另一个具有明确名称的函数。

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

另一种选择是将循环重写为不需要cont 变量,例如:

string teststring;
do
{
    cout << "Enter a string less than 10 characters long: ";
    getline(cin, teststring);
} while (teststring.length() >= 10);

cout << "Thank you.\n\n";

但这并不总是可行的,尤其是当您需要根据停止条件输出不同的消息时。

【讨论】:

    【解决方案3】:

    是的,如果您有充分的理由重复使用变量,那很好。锁守卫是我自己的代码中最常见的用法,Lightness 对std::stringstream ss 的回答中给出了示例。基本上在选择不同的变量名感觉更尴尬的任何时候都这样做。例如。如果您在代码中写入lock1lock2lock3、...。

    但是,更可接受的做法是将长函数体视为代码异味,并将它们重构为自己的函数。例如

    ...
    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
    }
    

    【讨论】:

    • 赞成std::lock_guard 点。将所有关键部分从函数中间的“自然”位置中取出到单独的函数中的想法是疯狂的。
    • 也就是说我可以建议 void foo(string& teststring) 吗?否则,您会引入可能很繁重的临时变量(如果测试字符串很大)。
    • @DanAllen 我试图保持简单(请参阅 Effective Modern C++ 中的第 41 项了解全部复杂性!)...但只是查看了 OPs 代码,他正在修改 teststring 所以,是的,它们绝对应该是参考!谢谢:-)
    【解决方案4】:

    这显然是一个玩具箱,但这是一个很好的做法,“独立”积木就是为此目的。 我碰巧相信与将其分解为(在许多情况下)没有单独目的的成员相比,它们是构建长函数的更好方法。

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

    但在这种情况下,您可能会考虑:

        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.\n\n";
                break; //<--- Escapes the loop.
            }
    
        }
    

    脚注(回应 cmets):

    您应该将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 的“坏业力”,因为他们“去”了一个非常明确定义的执行点。

    【讨论】:

    • 其实这很酷。所以即使没有条件,else 语句无论如何都会中断循环。这对于基本的东西来说很棒。仅在 while 循环条件中声明 bool 有什么问题吗?一段时间内的 for 循环是否有特定的优势?我是一个初学者,所以我只想完全理解它。我认为可能存在多个条件会结束循环的场景,而bool 在我看来更美观。
    • 我很喜欢这个。无论如何,for 循环都有更多的功能,并且只中断或具有多个完成条件的选项也很棒。谢谢!
    猜你喜欢
    • 2014-05-31
    • 2012-09-04
    • 1970-01-01
    • 1970-01-01
    • 2019-11-14
    • 1970-01-01
    • 2014-11-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多