所以我理解在C#中使用var
是有意义的,因为你有编译器派生的匿名类型。 C ++似乎没有这个功能(除非我错了),那么拥有auto
关键字有什么意义呢?
(有点酷,与C#不同,auto
对成员/全局变量有效,我觉得这很酷,但似乎不足以证明它的存在。)
答案 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
有很多用途
匿名函数对象,又名闭包,又名lambda实例。 auto
是存储它们的唯一方法。也可以无限制地生成从这些类型和背面类型派生的类型。
C ++可以有非常复杂的类型,例如非变异迭代器的类型,它使用自定义分配器和散列函数的无序映射。 typedef
可以缓解此问题,但具有特定名称的m.begin()
的类型不具备信息性:foo_iterator it =
与auto foo_iterator =
一样有意义,auto
一个人不需要其他地方的样板。
返回类型推导使用auto
关键字,这是执行某些template
函数所必需的,没有大量的特征样板。消除样板是一个常见的主题:C ++的健壮类型系统意味着类型可以携带大量信息,并且在每次使用时对其进行编码都会适得其反。
在一些ducktype template
代码中,推断变量类型的工作与编码变量值的工作大致相同,结构几乎完全相同,有时甚至是字面上的:{{ 1}}。 decltype(long expression) x = long expression;
消除了重复。
最后在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。