'auto'关键字有什么意义?

时间:2013-07-17 01:41:05

标签: c++ c++11

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

(有点酷,与C#不同,auto对成员/全局变量有效,我觉得这很酷,但似乎不足以证明它的存在。)

8 个答案:

答案 0 :(得分:33)

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(); ...)

VS

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

这也很有用。

答案 1 :(得分:15)

C ++中auto有很多用途

  1. 匿名函数对象,又名闭包,又名lambda实例。 auto是存储它们的唯一方法。也可以无限制地生成从这些类型和背面类型派生的类型。

  2. C ++可以有非常复杂的类型,例如非变异迭代器的类型,它使用自定义分配器和散列函数的无序映射。 typedef可以缓解此问题,但具有特定名称的m.begin()的类型不具备信息性:foo_iterator it =auto foo_iterator =一样有意义,auto一个人不需要其他地方的样板。

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

  4. 在一些ducktype template代码中,推断变量类型的工作与编码变量值的工作大致相同,结构几乎完全相同,有时甚至是字面上的:{{ 1}}。 decltype(long expression) x = long expression;消除了重复。

  5. 最后在C ++ 1y中,输入deduction lambdas使用auto来表示参数是推导出的。轻量级auto。谈到扩展到非lambdas也在臭鼬工作。

答案 2 :(得分:5)

我是一个真实的例子,我不能,不使用自动

我试图在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

答案 3 :(得分:3)

C ++确实有“匿名”类型 - 您无法通过名称引用的类型,因为您无法使用该名称。甚至在C ++ 11和lambdas之前就是这种情况。请考虑以下代码:

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的结果类型不是由规范定义的。

答案 4 :(得分:2)

语法糖

我宁愿说

auto i = mapping.begin();

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

答案 5 :(得分:1)

非常值得阅读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);

答案 6 :(得分:1)

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

   auto i = expressions;

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

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

答案 7 :(得分:0)

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

在C ++ 11之前,必须明确声明c ++中的所有变量,但是在发布c ++ 11之后,编译器本身会在运行时推断出变量的类型。

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