【问题标题】:What is the point of the 'auto' keyword?“auto”关键字的意义何在?
【发布时间】:2013-07-15 09:54:06
【问题描述】:

所以我理解在 C# 中使用 var 是有意义的,因为您有编译器派生的匿名类型。 C++ 似乎没有这个特性(除非我错了),那么有一个auto 关键字有什么意义呢?

(有点酷,与 C# 不同,auto 确实适用于成员/全局变量,我想这很酷,但似乎不足以证明它的存在)。

【问题讨论】:

  • 我不会使用“编译器派生的匿名类型”来描述var,而是为开发人员消除冗余/痛苦的*类型声明。 *请参阅 LINQ 编辑:哦,等等,是的,您可以将它用于匿名类型。不理我。 :)
  • 这确实是您唯一一次使用var。当结果为匿名时,您只需要在 LINQ 表达式中使用var
  • C++ lambdas 是匿名类型,很像 C# lambdas。在这种情况下,autostd::function 的用途分别与 varFunc 相同。
  • C++ lambdas are of anonymous types, much like C# lambdas. 这是一个很好的观点。不久前我遇到过。
  • GCC 和 Clang 对 C++11 的支持比 MSVC 好很多。

标签: c++ c++11


【解决方案1】:

auto 在涉及泛型编程和节省程序员一些打字时有很多用途。

例如,考虑一下。您愿意输入:

std::unique_ptr<name::long_type::goes_here> g = 
    std::make_unique<name::long_type::goes_here>(1,2,3,4)

或:

auto g = std::make_unique<name::long_type::goes_here>(1,2,3,4)

是的,它们都很长,但是我们知道返回类型并再次指定它有点麻烦。这也适用于迭代器:

for(auto i = vec.begin(); ...)

对比:

for(std::vector<type>::iterator i = vev.begin(); ...)

它在泛型编程中的用途也是确定函数的返回类型,或者如果您正在执行一些您不知道类型的泛型算法。

例如,考虑一个非常基本的例子。

template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) {
    return t + u;
}

这允许编译器找出加法操作的类型,而不是我们自己试图找出它。请注意,在 C++14 中,您可以省略尾随返回类型。它在泛型编程中的使用也不止于此。如果我们想使用任何类型的容器作为算法的包装函数,我们可以使用auto 来帮助我们。例如:

template<class Cont>
void my_sort(Cont&& cont) {
    using std::begin;
    auto first = begin(std::forward<Cont>(cont));
    // work with the iterators here
}

在未来 (C++14) 中,auto 也可用于制作多态 lambda,例如:

[](auto a) { return a + 4; }

这也很有用。

【讨论】:

  • Rapptz,将代码提取到代码块中以使差异更加明显。希望你不要介意。如果您这样做,这里有一个 +1 来补偿您 :-) 开个玩笑,+1 是因为它是一个很好的答案。
  • @paxdiablo 谢谢!我也想这样做:)
  • @sircodesalot C++14 是一个“次要”版本。没有 C++11 大,但带来了一些非常好的东西来玩,比如多态 lambda、可选、省略函数的尾随返回类型和其他有趣的东西。
  • @sircodesalot:“我刚开始下载 Visual Studio 2013 预览版。太疯狂了。” 怎么这么“疯狂”?这是一个每年发布的时间表。 Firefox 将在一年内发布 8 个版本,Chrome 也将发布这么多。如果有的话,与 Clang(每年 2 个)和 GCC 相比,VS 的发布计划很慢。
  • @NicolBolas:区别蜂鸣,VS 相当昂贵……
【解决方案2】:

auto 在 C++ 中有多种用途

  1. 匿名函数对象,又名闭包,又名 lambda 实例。 auto 是存储它们的唯一方法。类型也可以从这些类型中派生出来,并在它们背后的类型,无穷无尽。

  2. C++ 可以有相当复杂的类型,例如将非变异迭代器的类型转换为使用自定义分配器和散列函数的无序映射。 typedef 可以缓解这种情况,但是具有特定名称的 m.begin() 的类型并没有那么丰富的信息:foo_iterator it =auto foo_iterator = 一样有意义,而 auto 在其他地方不需要样板。

  3. 返回类型推导使用auto 关键字,这是在没有大量特征样板的情况下执行一些template 函数所必需的。消除样板是一个共同的主题:C++ 强大的类型系统意味着类型可以携带大量信息,而在每次使用时对其进行编码可能会适得其反。

  4. 在一些ducktype template 代码中,推断变量类型的工作与编码变量值的工作大致相同,并且在结构上几乎相同,有时是字面意思:decltype(long expression) x = long expression;auto 消除了这种重复。

  5. 最后,在 C++1y 中,类型推导 lambda 使用 auto 表示参数是推导的。有点轻量级template。将其扩展到非 lambdas 的讨论也在 skunkworks 中。

【讨论】:

【解决方案3】:

这是一个真实的例子,我不能,不使用 auto

我试图在 C++ 中执行 switch 类型语句,其中返回类型是特定于实现的,并且无法轻松声明。因此,使用“auto”可能是解析类型查找以查找地图声明的正确方法。

auto foo = boost::bind(&VegaFactory::load_commodity_one_leg,this,conn,_1);
std::map<std::string,decltype(foo)> methods;
methods.insert(std::make_pair("FOO",commodityOneLeg));

auto f = methods.find(bar);
// Call f here

【讨论】:

  • 这个可以用std::function代替auto,所以不使用auto也不是不可能...
【解决方案4】:

C++ 确实有“匿名”类型——你不能通过名字来引用这些类型,因为你无法使用这个名字。甚至在 C++11 和 lambda 之前就是这种情况。考虑以下代码:

class foo {
    class bar { 
      public:
        void baz() { }
    };
  public:        
    static bar func() { return bar(); }
};

foo::func().baz(); // OK, only the name "bar" is private
??? a = foo::func(); // Umm...
auto b = foo::func(); b.baz(); // Hooray!

即使实际上没有在私有作用域中声明,库在其 API 中保留一些未指定的类型通常很有用 - 特别是在大量使用表达式模板或其他模板元编程时,类型名称可以任意长,所有嵌套模板参数。甚至标准本身也这样做 - 例如,std::bind 的结果类型未由规范定义。

【讨论】:

  • 哦,我明白你的意思了。很有趣。
【解决方案5】:

语法糖

我宁愿说

auto i = mapping.begin();

结束

std::map<int, int>::iterator i = mapping.begin();

【讨论】:

    【解决方案6】:

    非常值得阅读 Herb Sutter 的文章 Almost Always Auto,了解为什么值得在显式类型上使用 auto 的一些很好的例子。主要优点是减少了输入,并且在底层类型发生变化时提供了额外的安全性。我最喜欢的例子之一是它如何减少重复。如果你在堆栈上分配,那么你会使用:

    MyClass c(param);
    

    但是,如果你想在你需要的堆上创建:

    MyClass* c=new MyClass(param);
    

    所以你不得不复制MyClass,但是RHS已经强制变量成为MyClass指针,所以你可以使用它来代替:

    auto c=new MyClass(param);
    

    如果您想将其声明为unique_ptr,那么之前您需要:

    unique_ptr<MyClass> c=make_unique<MyClass>(param);
    

    可简写为:

    auto c=make_unique<MyClass>(param);
    

    【讨论】:

      【解决方案7】:

      在 C++ 中,auto 关键字提供了一种类型推导机制。例如,

         auto i = expressions;
      

      auto 关键字告诉编译器从赋值运算符右侧的表达式中确定变量 i 的类型。

      因此,如果表达式的值是双倍的,那么变量 i 将是双倍的。或者,如果表达式的值为 bool,那么变量 i 将是 bool。

      【讨论】:

        【解决方案8】:

        所以,我们先来学习类型推断,它基本上是指编程语言中表达式的数据类型的自动推断。

        在 C++ 11 之前,c++ 中的所有变量都必须显式声明,但在 c++ 11 发布之后,编译器会在运行时自行推断变量的类型。

        我们可以将它用于变量,甚至用于函数返回类型。 但是,建议避免在函数返回类型中使用 auto。

        【讨论】:

        • 这是不正确的。编译器在运行时不推导出任何内容,它不可能这样做,因为在您能够运行生成的可执行文件时编译器尚未运行。编译器只在编译时运行,变量的类型在编译时推导出来。
        猜你喜欢
        • 2011-04-16
        • 2010-09-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-16
        • 2011-02-20
        • 2014-12-24
        • 2011-06-08
        相关资源
        最近更新 更多