【问题标题】:Reuse of variable of type auto重用 auto 类型的变量
【发布时间】:2020-03-27 16:28:38
【问题描述】:

我有一个特殊的类用作方法的返回类型,包含所需的值,或者在失败的情况下,甚至会从早期的错误中级联错误消息。它按预期工作。

由于返回的类型不同,我喜欢使用关键字 auto。但是当使用很多方法时,我必须创建新的返回变量。

代码的典型部分如下所示:

auto ret1 = methodA();
if(ret1.isValid()...

auto ret2 = methodB();
if(ret2.isValid()...

我不喜欢总是创建一个新变量。但我喜欢优雅的错误处理方式。使用更多的转储返回类型(如整数中的错误代码)可以解决问题,但我无法从错误处理返回类型中受益。

重用第一个返回变量ret1有什么技巧吗?

【问题讨论】:

  • 它们是同一类型吗?如果是,则只需 ret1 = methodB(),如果否,则否,因为 ret1 已经有一个类型。
  • 自动在编译时计算:stackoverflow.com/questions/19618759/…
  • auto 只是实际类型的替代品,其背后并没有更多的魔力。因此,如果 methodAmethodB 返回不同的东西,答案是否定的。换句话说,您可以将auto 替换为实际类型,您的问题仍然是一样的
  • 您可以让isValid 获取一个可调用对象,该可调用对象仅在值有效时才被调用。然后你根本不需要存储返回值。如果合适,很大程度上取决于您的用例。 Lambda 使传递内联可调用对象变得非常容易和可读。
  • 你为什么不喜欢总是创建一个新变量?你的物体很大吗?

标签: c++ auto


【解决方案1】:

您必须创建新的作用域才能将变量名称重用于不同的变量,例如:

{
    auto ret = methodA();
    if (ret.isValid()) ...
}
{
    auto ret = methodB();
    if (ret.isValid()) ...
}

您还可以利用if 创建的范围,将 init-statement 放入其中:

if (auto ret = methodA(); ret.isValid()) ...

if (auto ret = methodB(); ret.isValid()) ...

【讨论】:

  • 后者需要C++17。在此之前 if(auto ret = methodA()) 为返回类型定义了转换为布尔值作为 isValid() 的替换可能会很好。
  • FWIW 我最近一直在使用后一种模式加载,它很可爱。
【解决方案2】:

auto 不是类型。

它是一个关键字,表示“将类型放在此处,通过从初始值推导出它”。这发生在编译期间,一次。

无论您是否使用auto,您都不能重用ret1 来存储不同类型的对象。

这应该不是问题。如果您担心“名称用尽”或“有许多相似的名称”,说明您的名称描述性不够和/或范围不够紧凑。

【讨论】:

    【解决方案3】:

    auto 不是一种类型。在auto foo = bar(); 中,编译器简单地计算出bar() 实际返回的类型并将其替换。因此,如果bar() 返回int,那么这就是foo 的类型,如果它返回bool,那么那个foo 的类型。并且一旦确定了(第一次)应该替换auto 的类型,那么它就永远不会改变。 auto 不是“变量类型”的意思,它只是表示“嘿编译器,我懒得弄清楚类型放在这里,请为我做”,但是 没有区别what-so - 永远 与您自己编写最终类型相比。 因此,如果您第二次分配给它的变量与第一次分配的类型相同,则可以重用该变量 - 否则不是。

    【讨论】:

    • 而且,老实说,我一直对“重用变量”这个术语持谨慎态度,因为你甚至不能这样做;一个对象是一个对象是一个对象。您不能通过重用范围内的名称来替换对象。但是通过适当的分配语义,您可以使用另一个对象作为源材料来对其进行变异;)可能听起来像吹毛求疵,但我认为这归结为人们如何理解对象的“身份”以及= 不会替换对象或创建一个新的。诚然,在某种抽象层次上,我们可以这样想。操作做得对。
    • @AsteroidsWithWings 我知道细节。我试图提供一个简单、脚踏实地的解释,让新手产生共鸣。如果我们过于技术化,非专家通常会迷失基本观点。
    • 我知道你知道,我只是将它放在那里以供其他人使用,并且可能会在措辞上稍作调整,以免我们不小心误导/误导人们。对不起。
    • @AsteroidsWithWings 没什么可“抱歉”的。
    • 太好了,我很高兴。 :)
    【解决方案4】:

    我不喜欢总是创建一个新变量。

    更好的是创建一个const 变量:

    const auto ret1 = methodA();
    if(ret1.isValid()...
    
    const auto ret2 = methodB();
    if(ret2.isValid()...
    

    在这种情况下,您需要将const 设为isValid 之类的所有方法,但这更好:“is”不应该有副作用并修改状态。

    下一步是完全删除临时变量:

    if(methodA().isValid()) {
        ...
    }
    
    if(methodB().isValid()) {
        ...
    }
    

    另一种方法是将每个函数调用包装到一个块中:

    {
        const auto ret = methodA();
        if(ret.isValid()...
    }
    
    {
        const auto ret = methodB();
        if(ret.isValid()...
    }
    

    这允许您重用 const 变量名称。

    每个块都成为提取到单独函数的候选者(参见“清洁代码”中的 Bob 大叔)。

    【讨论】:

      猜你喜欢
      • 2020-12-18
      • 1970-01-01
      • 1970-01-01
      • 2012-04-12
      • 1970-01-01
      • 2020-04-22
      • 2018-12-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多