主机开设成功 网站正在建设中,最权威最有效的投诉平台,营销与销售的区别,重庆公司核名在哪个网站背景#xff1a;旧标准的auto
在旧标准中#xff0c;auto代表“具有自动存储期的 局部变量”
auto int i 0; //具有自动存储期的局部变量
//C98/03#xff0c;可以默认写成int i0;
static int j 0; //静态类型的定义方法实际上#xff0c;我们很少使用auto#xff0c…背景旧标准的auto
在旧标准中auto代表“具有自动存储期的 局部变量”
auto int i 0; //具有自动存储期的局部变量
//C98/03可以默认写成int i0;
static int j 0; //静态类型的定义方法实际上我们很少使用auto因为非static即“具有自动存储期的”所以不用人为去写auto
因此在C11中auto关键字不再表示存储类型指示符如static、register、mutable等都属于storage-class-specifiers而是改成了一个类型指示符type-specifier。
auto初探
不同于Python等动态类型语言的运行时变量类型推导隐式类型定义如auto x 5;的类型推导 发生在编译期。它的作用是让编译器自动 推断出这个变量的类型而不需要显式指定类型
auto x 5; //OK: x是int类型
//字面量5是const int类型变量x将被推导为int类型const被丢弃
auto pi new auto(1); //OK: pi被推导为int*
const auto *v x, u6; //OK: v是const int*类型u是const int类型
//因为vu已经被推导为const int类型
//1. u必须初始化不然编译不予通过
//2. u的初始化不能使编译器产生二义性。如u6.6编译器会报错
static auto y - 0.0; //OK: y是double类型
auto int r; //error: auto不再表示存储类型指示符编译器报错
auto s; //error: auto无法推导出s的类型编译器报错隐式的类型定义也是 强类型定义 auto所在那行已经准确推断出其类型了auto只能用于 类型推导 不能用于存储类型指示符的推导比如auto int r 5;auto并不能代表一个实际类型的声明如s的编译器错误它只是一个类型声明的“占位符”auto声明的变量必须马上初始化以让编译器推断出它的实际类型并在编译时将其替换为真正的类型
推导规则
auto可以通指针、引用结合起来使用还可以带上cv限定符cv-qualifier, const和volatile限定符的统称
推导规则
当不声明为指针或引用时auto的推导结果和初始化表达式抛弃引用和cv限定符后类型一致当声明为指针或引用时auto的推导结果将保持初始化表达式的cv属性
int x 0;auto *a x; //a - int* auto被推导为int
auto b x; //b - int* auto被推导为int*
//auto不声明为指针也可以推导出指针类型
auto c x; //c - int auto被推导为int
auto d c; //d - int auto被推导为int
//当表达式是一个引用类型时auto会把引用类型抛弃const auto e x; //e - const int auto被推导为int
auto f e; //f - int auto被推导为int(non-const int)
//当表达式带有constvolatile也一样属性时auto会把const属性抛弃掉const auto g x; //e - const int auto被推导为int
auto h g; //f - const int auto被推导为const int//auto和引用或指针结合时auto的推导将保留表达式的const属性auto的推导和函数模板参数的自动推导
auto的推导和函数模板参数的自动推导有相似之处
上面的例子中的auto和下面的模板参数自动推导出来的类型是一致的
templatetypename T void func(T x) {} //T - auto
templatetypename T void func(T *x) {} //T* - auto *
templatetypename T void func(T x) {} //T - auto templatetypename T void func(const T x) {} //const T - const auto
templatetypename T void func(const T* x) {} //const T* - const auto*
templatetypename T void func(const T x) {} //const T - const auto因此在熟悉auto推导规则时可以借助函数模板的参数自动推导规则来帮助和加强理解。
auto的限制
void func(auto a 1) {} //error: auto不能用于函数参数struct Foo{auto var1_ 0; //error: auto不能用于非静态成员变量static const auto var2_ 0; //OK: var2_ - static const int//auto仅能用于推导static const的整形或枚举成员//1. 因为其他静态类型在C标准中无法就地初始化//2. 虽然C11可以接受非静态成员变量的就地初始化但却不支持auto类型非静态成员的初始化
};templatetypename T
struct Bar{};void main() {int arr[10] {0};auto aa arr; //OK: aa - int*//aa不会推导为int[10]而是int*auto rr[10] arr; //error: auto无法定义数组Barint bar;Barauto bb bar; //error: auto无法推导出模板参数
}什么时候用auto
迭代器类型等场景auto简化函数定义
不加选择地随意使用auto会带来代码可读性和维护性的严重下降。因此在使用auto的时候一定要权衡好。
auto简化函数定义
class Foo{
public:static int get(void) {return 0;}
};
class Bar{
public:static const char* get(void) {return 0;}
};templateclass A
void func(void){//对类型A都调用静态函数get来获取valauto val A::get();//对val做统一处理//...
}funcFoo();
funcBar();如果不用auto就不得不对func再添加一个模板参数并在外部调用时手动指定get()的返回值类型
class Foo{
public:static int get(void) {return 0;}
};
class Bar{
public:static const char* get(void) {return 0;}
};templateclass A, class B
void func(void){B val A::get();//...
}funcFoo, int();
funcBar, const char*();参考文章
参考书籍《深入应用C11》