What & How & Why

差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录前一修订版
后一修订版
前一修订版
cs:programming:cpp:courses:cpp_basic_deep:chpt_2 [2024/04/16 11:30] – [底层常量的隐式转换] codingharecs:programming:cpp:courses:cpp_basic_deep:chpt_2 [2024/04/16 15:09] (当前版本) – [对象生命周期] codinghare
行 329: 行 329:
 </code> </code>
 <WRAP center round tip 100%> <WRAP center round tip 100%>
-可以使用 std::is_same_v<type1, type2> 来判断类型是否相同+可以使用 std::is_same_v<type1, type2> 来判断类型是否相同。定义于 <type_traits> 头文件
 </WRAP> </WRAP>
 +====类型别名与自动推导====
 +===类型别名===
 +类型可以引入别名,便利使用(比如 ''size_t'' 实际上是一个 unsigned int)。别名的引入有两种方式:
 +  * typedef + type + alias
 +  * using alias = type
 +<code cpp>
 +//myInt 是 int 类型的别名
 +//推荐使用 using
 +//别名实际上是 myCharArr, 但 typedef 的引用看起来非常 confusing
 +typedef char myCharArr[4];
 +using myCharArr = char[4];
 +</code>
 +==类型别名与指针和引用==
 +  * 当使用别名定义指针时,别名代表了指针的整体。此时如果使用 ''const'' 修饰别名,那么 ''const'' 修饰的是指针,也就是将指针定义为**常量指针**。换句话说,下面两者等价:
 +<code cpp>
 +using intP = int*;
 +int x = 3;
 +
 +//别名定义
 +const intP constIntPAlias = &x;
 +//等同于 top-const pointer
 +int* const constIntP = &x;
 +</code>
 +  * 不能使用别名来创建引用的引用
 +===类型推导===
 +C++11 允许使用 ''auto'' 关键字让编译器自动通过**初始化表达式**的结果推断变量的类型:
 +<code cpp>
 +auto x = 3.5 + 15l;
 +</code>
 +==auto==
 +  * ''auto'' 推导出的类型是强类型(定义时已经确定)
 +  * 因为需要初始化表达式推导类型,因此自动推导下,表达式**必须初始化**
 +  * ''auto'' 可能会导致类型退化
 +<code cpp>
 +int x1 = 3;
 +int& ref = x1;
 +//类型退化,ref 作为右值,此处由 int& 退化为 Int, 而不是 int&
 +int y = ref;
 +//auto 导致类型退化, ref2 是 int 类型
 +auto ref2 = ref;
 +</code>
 +  * ''const / constexpr'' 与 ''auto'' 组合会推导出常量 / 常量表达式类型
 +<code cpp>
 +//const int 
 +const auto x1 = 3;
 +//const int& 
 +const auto& x2 = 3;
 +
 +const int x3 = 3;
 +//const int
 +const auto y1 = x3;
 +//int (top-const 的退化)
 +auto z = x3;
 +</code>
 +  * auto 加引用会避免退化
 +<code cpp>
 +//不会退化,const int&
 +auto& y2 = x3;
 +</code>
 +  * 数组的推导会退化为指向数组首元素的指针
 +<code cpp>
 +int x[3] = {1,2,3};
 +//int*
 +auto x1 = x;
 +//加引用不会退化:int(&)[3] 
 +auto& x2 = x;
 +</code>
 +==decltype==
 +decltype 获取一个表达式,并返回表达式的类型。decltype 与 auto 的区别在于,decltype **不会产生类型退化**。
 + 
 +   * decltype(val):''val'' 代表 entity(**变量名称**),那么 ''val'' 是什么类型,那么返回的就是什么类型
 +<code cpp>
 +//x is an variable name
 +int x = 3;
 +//int
 +decltype(x);
 +//注意加括号的形式,(x) 是表达式, x 是变量名
 +//int&
 +decltype((x));
 +</code>
 +  * ''decltype(exp(r-value))'' :如果表达式是非变量名称的表达式,且为右值,那么返回的是表达式评估后的类型:
 +<code cpp>
 +int x = 3;
 +int& y1 = x;
 +//int
 +auto y2 = y1;
 +//int&
 +decltype(y1) y3 = y1;
 +</code>
 +  * ''decltype(exp(l-vaule))'':如果表达式为非变量名称的左值(通常带运算符),返回的类型会自动加上一个**引用**
 +<code cpp>
 +int x = 3;
 +int* ptr = &x;
 +//*ptr 是包含了解引用操作符的表达式:此处是 l-value,此处得到的是 int& 
 +decltype(*ptr);
 +</code>
 +  * decltype(auto) [C++14]:用于简化 decltype 的使用
 +<code cpp>
 +//非常繁琐的写法
 +decltype(3.5+15l) x  = 3.5 + 15l;
 +//C++ 14 的写法
 +// 用 auto 来代表繁琐的表达式,并不会导致退化
 +// 编译器会将 auto 替换为赋值运算符右边的内容
 +decltype(autol) x  = 3.5 + 15l;
 +</code>
 +  * concept auto [C++20]:任何 concept 都会包含一系列类型,这些类型的共同特征都可以用 concept 表示。比如 ''int'', ''long'' 都可以表示为 ''std::intergal''
 +    * concept auto 让自动推导受 concept 的范围限制,比如让 auto 只能推断出整数类型的类型:
 +<code cpp>
 +#include <concepts>
 +int main()
 +{
 +    //int
 +    std::integral auto z = 3;
 +    //error, 3.5 is not an integral
 +    std::integral auto z = 3.5;
 +}
 +</code>
 +====域和对象生命周期====
 +===域 Scope===
 +域代表了程序的一部分,域中的 name 有**唯一的含义**:
 +  * 全局域:程序最外部的域,全局对象
 +  * 块域:大括号限定的域,局部对象
 +  * 其他类型的域:Namespace, class 等等
 +域可以进行嵌套,内部域中的 Name 会掩盖外部域中的 Name:
 +<code cpp>
 +int x = 3;
 +int main()
 +{
 +   int x = 4;
 +   //call local x
 +   std::cout << x << '\n';
 +}
 +</code>
 +===对象生命周期===
 +生命周期指对象从被**初始化到被销毁**的区间。
 +  * 全局对象:生命周期为程序的运行期
 +  * 局部对象:起始于**初始化**,结束于域的执行完成