CC++编程:auto

xiaoxiao2021-02-28  60

一、C的auto

#include <stdio.h> void main() { auto int a; // }

auto声明自动变量,在栈上,自动分配自动回收,但是在CPP中不能这样用

二、C++的auto

 

1、auto的作用

(1)自动推导类型

#include <iostream> using namespace std; void main() { auto num0 = 10; cout << typeid(num0).name() << endl; auto num1 = 10.1; cout << typeid(num1).name() << endl; auto num2 = 'c'; cout << typeid(num2).name() << endl; auto num3 = "abc"; cout << typeid(num3).name() << endl; //char const * auto num4 = L"abc"; cout << typeid(num4).name() << endl; //wchar_t const * cin.get(); }

 

总结:CPP中,auto是一种自适应类型,它会根据初始化的变量而自动推导类型,不能和int,double等关键字相结合。

auto 让编译器通过初始值来进行类型推演。从而获得定义变量的类型,所以说 auto 定义的变量必须有初始值。

应用场景

当变量类型名很长时使用auto自动推导类型用auto当变量类型不确定时用auto

(2)返回值占位

#include <iostream> using namespace std; template <typename T1, typename T2> auto compose(T1 t1, T2 t2) { return t1 + t2; } void main() { cout << compose(1, 11.1) << endl;//错误 cin.get(); }

 

#include <iostream> using namespace std; template <typename T1, typename T2> auto compose(T1 t1, T2 t2) -> decltype(t1 + t2) { return t1 + t2; } void main() { cout << compose(1, 11.1) << endl;//错误 cin.get(); }

总结:

函数模板中,与decltype结合表示函数返回的类型decltype操作符用于查询表达式的数据类型。auto在这里的作用也称为返回值占位,它只是为函数返回值占了一个位置,真正的返回值是后面的decltype(t1 + t2)

当模板函数的返回值依赖于模板的参数时,我们依旧无法在编译代码前确定模板参数的类型,故也无从知道返回值的类型,这时我们可以使用auto。

 

2、注意事项

(1)、auto变量必须初始化

#include <iostream> using namespace std; void main() { auto i; //无法推导:“auto”类型(需要初始值设定项) cin.get(); }

包括定义在堆上的auto也必须初始化

#include <iostream> using namespace std; int main() { int* pp = new auto(); //错误 C2119 "new-expression": 无法从空的初始值设定项推导 "auto" 的类型 auto x = new auto();//错误 C2119 "new-expression": 无法从空的初始值设定项推导 "auto" 的类型 cin.get(); }

正确的代码应该是:

#include <iostream> using namespace std; int main() {     int* pp = new auto(1);     auto x = new auto(11.1);     auto* y = new auto(9);     cin.get(); }

总结:auto变量必须初始化,以便从初始化表达式中推导出变量类型。对比const

(2)、auto不能与其他类型组合连用

#include <iostream> using namespace std; void main() { auto int a; //“auto”不能与任何其他类型说明符组合 cin.get(); }

(3)函数参数不能被声明为auto

#include <iostream> using namespace std; void MyFunction(auto parameter ) {}; //错误 C3533 参数不能为包含“auto”的类型5 void MyFunction1(auto parameter = 3) {}; //错误 C3533 参数不能为包含“auto”的类型5 void main() { cin.get(); }

(4)函数模板不能使用auto

#include <iostream> using namespace std; template<auto T> void Fun(T t) {} void main() { cin.get(); }

(5)定义在一个auto序列的变量必须始终推导成同一类型

#include <iostream> using namespace std; void main() { auto x1 = 5, x2 = 5.0, x3 = 'r'; //错误 C3538 在声明符列表中,“auto”必须始终推导为同一类型 cin.get(); }

使用auto可以在一个语句中声明多个变量,但是因为一个声明中只能有一种基本数据类型,所以该语句中私有变量的初始基本类型必须是一样的。

注意区分数据类型和类型修饰符:

#include <iostream> using namespace std; void main() { int i(3);; //()仅用于初始化 auto a = i, &b = i, *c = &i;//正确: a初始化为i的副本,b初始化为i的引用,c为i的指针. auto i1=0,*p=&i1;     //正确,i1是整数,p是指向i1的指针 cin.get(); }

 

(6)auto不能自动推导成CV-qualifiers(constant& volatile qualifiers),除非被声明为引用类型

 

auto会忽略引用

#include <iostream> using namespace std; void main() { int a{ 10 }; cout << typeid(a).name() << endl; //int int &b = a; //将a的值取出来放入b b = 11; cout << typeid(b).name() << endl; //int //b是一个引用,去除引用 int &d = b; d = 12; cout << typeid(d).name() << endl; //int auto c = b; c = 12; cout << typeid(c).name() << endl; //int auto &e = b; e = 13; cout << typeid(e).name() << endl; //int         //b,c,e是同一块内存 cin.get(); } #include <iostream> using namespace std; void main() {     const int a1{ 10 };     //a1 = 12;  //C3892    “a1” : 不能给常量赋值         cout << "const int a1 = "<< a1 << "    "<< typeid(a1).name() << endl;  //int          int b1 = a1;   //推导:取出a的值赋值给b分配的空间     const auto b2 = a1;  //b是新内存,是const int *     b1 = 12;     //    b2 = 12;  //C3892    “b2” : 不能给常量赋值         cout << "int b1 = " << b1 << "    " << typeid(b1).name() << endl;  //int     auto c0 = a1;   //只是将a1的值赋值过来,是int类型     c0 = 12;     cout << "auto c0 = " << c0 << "    " << typeid(c0).name() << endl;     //int &c1 = a1; //C2440    “初始化” : 无法从“const int”转换为“int &”    、     auto &c1 = a1;  //b和c是同一块内存 //    c1 = 12;   //C3892    “c1” : 不能给常量赋值         cout << "auto &c1 =" << c1 << "    " << typeid(c1).name() << endl;     cin.get(); }

总结:如果初始化表达式为const或volatile(或者两者兼有),则除去const/volatile语义。如果auto关键字带上&号,则不去除const语意。=是赋值,&是别名

使用auto时,当传递的是const变量的时候,必须手动加上const,因为auto不会自动推倒成const,除非和引用连用。 #include <iostream> using namespace std; void main() { const int a = 1; const auto b = a; //b是const auto auto c = a;//c的类型为int auto& d = a;//d的类型为const int & cin.get(); }

(7)auto会退化成指向数组的指针,除非被声明为引用

#include <iostream> using namespace std; void main() { int a3[3] = { 1, 2, 3 }; auto b3 = a3; cout << typeid(b3).name() << endl; //int * int a7[3] = { 1, 2, 3 }; auto & b7 = a7; cout << typeid(b7).name() << endl; //int [] cin.get(); }

(8)auto是一个占位符,不是类型,不能用于类型转换或其它一些操作,如sizeof、typeid

#include <iostream> using namespace std; void main() { cout << sizeof(auto) << endl;//错误 cout << typeid(auto).name() << endl;//错误 cin.get(); }

(9)无法强制转换为包含“auto”的类型

#include <iostream> using namespace std; void main() { auto * p = auto(3); // 无法强制转换为包含“auto”的类型 cin.get(); } 建议:大多数情况使用关键字auto,除非非常需要转换。

三、CPP中for auto副本打印数组

#include <iostream> using namespace std; void main() { int a[5]{ 1, 2, 3, 4, 5 }; for (auto i : a) //auto 1是一个副本,会将a内存里面的值原样赋值 { i += 1; cout << i << endl; //2, --- 6 } for (auto i : a) //auto 1是一个副本,会将a内存里面的值原样赋值 { cout << i << endl; //1, 2, 3, 4, 5 } cin.get(); }

总结:auto i是一个副本,会将数组元素原样赋值给i

如果要修改auto副本:for(auto &i : a),也就是声明为引用

#include <iostream> using namespace std; void main() { int a[5]{ 1, 2, 3, 4, 5 }; for (auto &i : a) { i += 1; cout << i << endl; //2,3,4,5, 6 } for (auto i : a) { cout << i << endl; //2,3,4,5, 6 } cin.get(); }

 

 

 

转载请注明原文地址: https://www.6miu.com/read-2631977.html

最新回复(0)