C++ auto 关键字的使用

本文详细解析了C++11中auto关键字的使用方法和注意事项,包括其在变量类型推断、模板函数定义及依赖模板参数类型的变量声明等方面的应用。同时,文章还强调了auto变量初始化、类型推导规则以及常见使用误区。

这篇文章对C++中的auto关键字的使用较为详细,故进行转载,并重新排版,留作日后复习的资料,也希望大家能有所收获。
转自:https://www.cnblogs.com/KunLunSu/p/7861330.html

C++98 auto

早在C++98标准中就存在了auto关键字,那时的auto用于声明变量为自动变量,自动变量意为拥有自动

的生命期,这是多余的,因为就算不使用auto声明,变量依旧拥有自动的生命期:

int a =10 ;  //拥有自动生命期
auto int b = 20 ;//拥有自动生命期
static int c = 30 ;//延长了生命期

C++98中的auto多余且极少使用,C++11已经删除了这一用法,取而代之的是全新的auto:变量的自动

类型推断。

C++11 auto

auto可以在声明变量的时候根据变量初始值的类型自动为此变量选择匹配的类型,类似的关键字还有

decltype。举个例子:

int a = 10;
auto au_a = a;//自动类型推断,au_a为int类型
cout << typeid(au_a).name() << endl;

typeid运算符可以输出变量的类型。程序的运行结果输出了

int

这种用法就类似于C#中的var关键字。auto的自动类型推断发生在编译期,所以使用auto并不会造成程序运行时效率的降低。而是否会造成编译期的时间消耗,我认为是不会的,在未使用auto时,编译器也需要得知右操作数的类型,再与左操作数的类型进行比较,检查是否可以发生相应的转化,是否需要进行隐式类型转换。

auto的用法

上面举的这个例子很简单,在真正编程的时候也不建议这样来使用auto,直接写出变量的类型更加清晰易懂。下面列举auto关键字的正确用法。

用于代替冗长复杂、变量使用范围专一的变量声明。
想象一下在没有auto的时候,我们操作标准库时经常需要这样:

#include<string>
#include<vector>
int main()
{
    std::vector<std::string> vs;
    for (std::vector<std::string>::iterator i = vs.begin(); i != vs.end(); i++)
    {
        //...
    }
}

这样看代码写代码实在烦得很。有人可能会说为何不直接使用using namespace std,这样代码可以短一

点。实际上这不是该建议的方法(C++Primer对此有相关叙述)。使用auto能简化代码:

#include<string>
#include<vector>
int main()
{
    std::vector<std::string> vs;
    for (auto i = vs.begin(); i != vs.end(); i++)
    {
        //..
    }
}

for循环中的i将在编译时自动推导其类型,而不用我们显式去定义那长长的一串。

在定义模板函数时,用于声明依赖模板参数的变量类型。

template <typename _Tx,typename _Ty>
void Multiply(_Tx x, _Ty y)
{
    auto v = x*y;
    std::cout << v;
}

若不使用auto变量来声明v,那这个函数就难定义啦,不到编译的时候,谁知道x*y的真正类型是什么呢?

模板函数依赖于模板参数的返回值

template <typename _Tx, typename _Ty>
auto multiply(_Tx x, _Ty y)->decltype(x*y)
{
    return x*y;
}

当模板函数的返回值依赖于模板的参数时,我们依旧无法在编译代码前确定模板参数的类型,故也无从

知道返回值的类型,这时我们可以使用auto。格式如上所示。

decltype操作符用于查询表达式的数据类型,也是C++11标准引入的新的运算符,其目的也是解决泛
型编程中有些类型由模板参数决定,而难以表示它的问题。

auto在这里的作用也称为返回值占位,它只是为函数返回值占了一个位置,真正的返回值是后面的

decltype(_Tx*_Ty)。为何要将返回值后置呢?如果没有后置,则函数声明时为:

decltype(x*y)multiply(_Tx x, _Ty y)

而此时x,y还没声明呢,编译无法通过。

注意事项

一、auto 变量必须在定义时初始化,这类似于const关键字。

二、定义在一个auto序列的变量必须始终推导成同一类型。

例如:

auto a4 = 10, a5 = 20, a6 = 30;//正确
auto b4 = 10, b5 = 20.0, b6 = 'a';//错误,没有推导为同一类型

使用auto关键字做类型自动推导时,依次施加一下规则:

三、auto关键字做类型自动推导的规则

1. 如果初始化表达式是引用,则去除引用语义。

int a = 10;
int &b = a;

auto c = b;//c的类型为int而非int&(去除引用)
auto &d = b;//此时c的类型才为int&

c = 100;//a =10;
d = 100;//a =100;

2. 如果初始化表达式为const或volatile(或者两者兼有),则除去const/volatile语义。

const int a1 = 10;
auto  b1= a1; //b1的类型为int而非const int(去除const)
const auto c1 = a1;//此时c1的类型为const int
b1 = 100;//合法
c1 = 100;//非法

3. 如果auto关键字带上&号,则不去除const语意。

const int a2 = 10;
auto &b2 = a2;//因为auto带上&,故不去除const,b2类型为const int
b2 = 10; //非法

这是因为如何去掉了const,则b2为a2的非const引用,通过b2可以改变a2的值,则显然是不合理的。

4.初始化表达式为数组时,auto关键字推导类型为指针。

int a3[3] = { 1, 2, 3 };
auto b3 = a3;
cout << typeid(b3).name() << endl;

程序将输出

int *

5.若表达式为数组且auto带上&,则推导类型为数组类型。

int a7[3] = { 1, 2, 3 };
auto & b7 = a7;
cout << typeid(b7).name() << endl;

程序输出

int [3]

6.函数或者模板参数不能被声明为auto

void func(auto a)  //错误
{
//... 
}

7.时刻要注意auto并不是一个真正的类型。

auto仅仅是一个占位符,它并不是一个真正的类型,不能使用一些以类型为操作数的操作符,如sizeof或

者typeid。

cout << sizeof(auto) << endl;//错误
cout << typeid(auto).name() << endl;//错误

转自:https://www.cnblogs.com/KunLunSu/p/7861330.html

参考:C++ 11 auto关键字

<think>好的,用户想了解C++auto关键字的用法和示例代码。首先,我需要回忆auto关键字C++中的作用。记得从C++11开始,auto用于自动类推导,让编译器根据初始化表达式推断变量的类。这样可以简化代码,特别是在类名很长或者复杂的时候,比如迭代器或者lambda表达式。 接下来,我应该分几个主要用途来讲解。第一,基本类推导,比如声明变量时替代显式类声明。例如auto i = 42;会自动推断为int。第二,用于容器迭代,比如在vector的循环中使用auto&来避免写冗长的迭代器类。第三,与函数返回值结合,不过C++14之后才支持auto作为函数返回类,需要提一下可能需要尾置返回类或者C++14的特性。第四,lambda表达式,用auto来存储lambda对象,这样可以方便地定义匿名函数。第五,结构化绑定,C++17的新特性,可以用auto来解包tuple或者结构体成员,这个可能对用户有帮助。 然后要考虑用户可能的疑问,比如auto使用限制。比如,auto不能用于函数参数(除非C++20的泛lambda),也不能用于非静态成员变量,或者在无法推断类的情况下会报错。需要提醒用户注意这些情况,避免误用。 示例代码部分,每个用途都应该有对应的代码片段。比如基本类推导的简单例子,容器迭代的循环示例,lambda表达式的使用,以及结构化绑定的例子。代码要简洁明了,突出auto的作用,同时注释解释关键点。 还要注意引用站内的资料,用户提供的引用中有提到auto与lambda和范围for循环的结合,以及类推导的例子。需要将这些引用自然地融入到回答中,比如在讲解相关部分时添加引用标记[^2][^3]。 另外,用户的问题可能还涉及auto的优缺点,比如提高代码可读性,减少错误,但也可能隐藏类信息导致理解困难。需要平衡说明,让用户了解何时适合使用auto。 最后生成的相关问题要围绕auto关键字展开,可能包括与decltype的区别、C++版本的影响、性能影响等,这些都是用户可能进一步想知道的内容。 检查是否有遗漏的部分,比如是否覆盖了主要用法,是否引用了正确的资料,示例代码是否正确,语法是否符合要求(行内公式用$,独立公式用$$)。确保回答结构清晰,分点明确,符合用户的要求。</think>### C++auto关键字的用法详解 #### 1. **基本类推导** `auto`关键字允许编译器根据初始化表达式自动推导变量类。例如: ```cpp auto x = 42; // x的类推导为int auto str = "hello"; // str的类推导为const char* std::vector<int> vec = {1, 2, 3}; auto it = vec.begin(); // it的类推导为std::vector<int>::iterator ``` 通过`auto`可简化代码,尤其在复杂类(如迭代器)中效果显著[^2][^3]。 --- #### 2. **用于容器遍历** 结合范围`for`循环,可简化容器元素的遍历: ```cpp std::vector<int> nums = {1, 2, 3}; for (auto& num : nums) { // 使用引用避免拷贝 num *= 2; // 修改容器内的值 } ``` 若无需修改元素,可用`const auto&`或`auto`直接拷贝。 --- #### 3. **与函数返回值结合** 从C++14开始,`auto`可用于函数返回值推导(需确保所有返回路径类一致): ```cpp auto add(int a, int b) -> int { // C++11需要尾置返回类 return a + b; } // C++14起可直接推导 auto multiply(double a, double b) { return a * b; } ``` --- #### 4. **处理Lambda表达式** `auto`可存储Lambda表达式对象,便于实现匿名函数: ```cpp auto lambda = [](int a, int b) { return a + b; }; int result = lambda(3, 5); // result = 8 ``` 结合泛Lambda(C++14),功能更灵活: ```cpp auto generic_lambda = [](auto x, auto y) { return x + y; }; ``` --- #### 5. **结构化绑定(C++17)** 解包元组或结构体成员时,`auto`可简化代码: ```cpp std::tuple<int, std::string, double> data{42, "test", 3.14}; auto [id, name, value] = data; // 解包为独立变量 ``` --- ### 注意事项与限制 1. **无法推导未初始化变量** ```cpp auto x; // 错误:缺少初始化表达式 ``` 2. **不能用于非静态成员变量** ```cpp class Example { auto value = 10; // 错误:非静态成员需显式类 }; ``` 3. **与引用和常量修饰符结合** 需显式指定`const`或`&`: ```cpp const auto& ref = get_large_object(); // 避免拷贝且不可修改 ``` --- ### 示例代码汇总 ```cpp #include <vector> #include <tuple> int main() { // 基本类推导 auto x = 10; auto str = "C++"; // 容器遍历 std::vector<int> vec{1, 2, 3}; for (auto& num : vec) { num += 1; } // Lambda表达式 auto sum = [](auto a, auto b) { return a + b; }; auto result = sum(3.5, 4); // result类为double // 结构化绑定 std::tuple<int, std::string> tpl{100, "example"}; auto [num, name] = tpl; return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值