有什么理由在C ++ 03中使用'auto'关键字吗?


85

请注意,此问题最初于2009年发布,在批准C ++ 11之前和在auto彻底改变关键字的含义之前。提供的答案与C ++ 03的含义(auto即指定的存储类)有关,而不与C ++ 11的含义(auto即自动类型推断)有关。如果您正在寻找有关何时使用C ++ 11的建议auto,则该问题与该问题无关。

在最长的时间内,我认为没有理由static在C中使用该关键字,因为在块范围之外声明的变量是隐式全局的。然后,我发现将变量声明为static块作用域内将赋予它永久的持续时间,而在块作用域之外(在程序作用域内)声明该变量将为其赋予文件作用域(只能在该编译单元中访问)。

因此,这仅给我留下了一个我可能尚未完全理解的auto关键字:关键字。除了“局部变量”之外,它还有其他含义吗?不管您想在任何地方使用它,对您而言,隐式所做的任何事情吗?auto变量在程序范围内如何表现?static auto文件范围中的变量是什么?除了完整性之外,此关键字还有其他用途吗?

Answers:


74

auto是一个存储类说明,staticregisterextern也。您只能在声明中使用这四个之一。

局部变量(无static)具有自动存储持续时间,这意味着它们从定义的开始一直到块的结尾。将auto放在它们前面是多余的,因为无论如何这都是默认设置。

我不知道在C ++中使用它的任何理由。在具有隐式int规则的旧C版本中,可以使用它来声明变量,例如:

int main(void) { auto i = 1; }

要使其有效语法或在赋值i范围内与赋值表达式保持歧义,应在范围内。但这无论如何在C ++中不起作用(必须指定类型)。有趣的是,C ++标准写道:

默认情况下,在块范围内声明为没有存储类说明符的对象或声明为函数参数的对象具有自动存储时间。[注:因此,自动说明符几乎总是多余的,并不经常使用;auto的一种用法是明确地将声明语句与表达式语句(6.8)区分开。—尾注]

它指的是以下情形,这可能是任一的流延aint或一个变量的声明a类型的int具有围绕冗余括号a。它始终被视为声明,因此auto此处不会添加任何有用的信息,而是对人类有用。但是话又说回来,人类最好去除周围多余的括号a,我会说:

int(a);

有了autoC ++ 0x的新含义,我不建议将C ++ 03x的含义与代码一起使用。


4
C ++编译器通常在标准之前的ARM时代就具有从函数返回值的隐式int ...在EMPIRE之前...
Daniel Earwicker,2009年

1
我只是认为它是我的编译器告诉我忘记转发声明函数的方式。它会告诉我,由于隐式int,我对函数的用法与声明方法不同。
卡森·迈尔斯

29
最好的部分是程序员过去常常编写“ auto”(四个字母)来避免编写“ int”(三个字母)。
Max Lybbert 09年

30
@Max-嘿,很多人说“ double-u-double-u-double-u”是“万维网”的缩写。
Daniel Earwicker 09年

3
@smichak不,“ volatile”是类型限定符。而不是确定在何处存储值,它会更改对易失限定类型的对象进行写入和读取的行为。可以有易失性合格的堆栈变量(自动存储类)以及易失性合格的静态存储持续时间变量(本地“静态”存储类,非本地变量)。除此之外,我不知道“ register volatile”是否是有效的组合:)
Johannes Schaub-litb 2012年

86

在C ++ 11中,auto具有新的含义:它允许您自动推断变量的类型。

为什么这样有用?让我们考虑一个基本示例:

std::list<int> a;
// fill in a
for (auto it = a.begin(); it != a.end(); ++it) {
  // Do stuff here
}

auto那里创建了类型的迭代器std::list<int>::iterator

这可以使一些非常复杂的代码更易于阅读。

另一个例子:

int x, y;
auto f = [&]{ x += y; };
f();
f();

在那里,auto推导将lambda表达式存储在变量中所需的类型。维基百科对此主题有很好的报道。


4
仍然不确定这是否是对auto的很好使用。代码应该易于阅读,不容易编写!
DanDan 2012年

38
我对您不屑一顾,但我发现它比迭代器类型的垃圾邮件更容易阅读。
Overv

17
而且,如果邹因决定将类从list <int>更改为其他类,则不必搜索每个迭代器声明并进行更改。
roslav 2012年

2
@KarateSnowMachine:如果需要const,则可以使用“ const auto”而不是“ auto”。
darth happyface

4
@darthconst auto it = a.begin();会给你一个const iterator,而不是const_iterator。您仍然应该更改元素,但是++it将无法编译。要获得const_iterator,您可以使用auto it = a.cbegin();
fredoverflow 2013年

35

auto关键字目前没有任何用途。没错,它只是重新声明了局部变量的默认存储类,真正有用的替代方法是static

它在C ++ 0x中具有全新的含义。这使您对它毫无用处有了一些了解!


1
哦,老兄,那是没有用的吗?我喜欢新的含义。它使某些代码不再那么冗长和多余。
卡森·迈尔斯

是的,在C#中使用了等效项之后,它可能会产生巨大的变化。在C ++中,如果您使用的表达式模板的类型非常复杂,以至于从来都不打算手工写出来,则在C ++中更是如此。
Daniel Earwicker 09年

7

GCCauto对于嵌套函数有特殊用途-请参见此处

如果您要在定义函数之前调用嵌套函数,则需要使用进行声明auto


这是一个很棒的尽管依赖编译器的auto实现。感谢您的研究:)
卡森·迈尔斯

3

据推测,“自动”告诉编译器自行决定将变量(内存或寄存器)放置在何处。它的类似物是“寄存器”,据说它告诉编译器尝试将其保存在寄存器中。现代编译器会忽略这两者,因此您也应该忽略它们。


1
不完全是-如果您使用“寄存器”声明它,则编译器不允许在变量上使用地址运算符(&foo),因为它在内存中不存在任何位置(因此没有地址)。
TimČas2011年

3

我使用此关键字来显式地记录对于基于堆栈的处理器而言对于功能至关重要的变量(将变量放置在堆栈上)。在从函数(或中断服务程序)返回之前修改堆栈时,可能需要此函数。在这种情况下,我声明:

auto unsigned int auiStack[1];   //variable must be on stack

然后我访问变量之外:

#define OFFSET_TO_RETURN_ADDRESS 8     //depends on compiler operation and current automatics
auiStack[OFFSET_TO_RETURN_ADDRESS] = alternate_return_address;

因此,auto关键字有助于记录意图。


我认为这只是发出信号,因为关键字实际上并没有强制执行堆栈放置,而不仅仅是省略了它。
underscore_d

2

根据Stroustrup的说法,在“ The C Programming Language”(第4版,涉及C 11)中,使用“ auto”的主要原因如下(第2.2.2节)(引用了Troustrup的词):

1)

该定义在很大的范围内,我们希望使类型对我们的代码读者清晰可见。

使用“自动”及其必要的初始化程序,我们可以一目了然地知道变量的类型!

2)

我们想要明确说明变量的范围或精度(例如,使用double而不是float)

我认为适合这种情况的情况如下:

   double square(double d)
    {
        return d*d; 
    }

    int square(int d)
    {
        return d*d; 
    }

    auto a1 = square(3);

    cout << a1 << endl;

    a1 = square(3.3);

    cout << a1 << endl;

3)

使用'auto'可以避免冗余并写长类型名称。

想象一下来自模板化迭代器的一些长类型名称:

(来自第6.3.6.1节的代码)

template<class T> void f1(vector<T>& arg) {
    for (typename vector<T>::iterator p = arg.begin(); p != arg.end();   p)
        *p = 7;

    for (auto p = arg.begin(); p != arg.end();   p)
        *p = 7;
}

1

在旧的编译器中,auto是声明局部变量的一种方法。如果没有auto关键字或类似关键字,就无法在Turbo C等旧编译器中声明局部变量。


1

C ++ 0x中自动关键字的新含义在自由观看/下载的视频讲座非常漂亮的描述微软的斯蒂芬T. Lavavej对STL在MSDN的第9频道网站上发现这里

整个课程值得一看,但是有关auto关键字的部分大约在29分钟左右。


0

除“局部变量”外,“自动”还有其他含义吗?

不在C ++ 03中。

不管您想在任何地方使用它,对您而言,隐式所做的任何事情都没有吗?

在C ++ 03中什么都没有。

自动变量在程序范围内如何表现?文件范围中的静态自动变量是什么?

功能/方法主体之外的关键字不允许。

除了为完整起见,此关键字是否还有其他用途[在C ++ 03中]?

令人惊讶的是。C ++设计标准包括与C的高度向后兼容性。C拥有此关键字,没有真正的理由禁止它或重新定义其在C ++中的含义。因此,目的是减少与C的不兼容性。

除了完整性之外,此关键字在C中是否还有其他用途?

我最近才学到一个:从B移植古代程序的便利性。C从一种叫做B的语言演变而来,其语法与C十分相似。但是,B没有任何类型。在B中声明变量的唯一方法是指定其存储类型(autoextern)。像这样:

自动我

此语法仍适用于C语言,等效于

因为在C中,存储类默认为auto,类型默认为int。我猜想,每个起源于B并移植到C的程序在当时实际上都是auto变量。

C ++ 03不再允许C风格的隐式int,但它保留了no-longer-exactly-usefulauto关键字,因为与隐式int不同,它不引起C语法的麻烦。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.