#ifndef LESSON_2_4_H
#define LESSON_2_4_H
#include
extern const int ciExt;
inline void print_ciExt()
{
std::cout << ciExt << std::endl;
}
#endif // !LESSON_2_4_H
#include "lesson_2_4.h"
#include
extern const int ciExt = 4;
void auto_test();
void practice_2_26();
void practice_2_27();
void practice_2_28();
void practice_2_29();
void const_test();
void constexpr_test();
void alias_test();
void decltype_test();
struct Foo{}; //注意分号
int main()
{
//通过 const 关键字将变量定义成一个常量,而且以后不能再改变,所以 const 对象必须初始化,只能进行不改变其内容的操作
//const 对象默认仅在文件内有效,如果需要多文件共享,需要在声明和定义时,使用 extern 关键字(在函数中进行该操作会报错)
print_ciExt(); //4 头文件中 ciExt 和本文件中的 ciExt 是同一个对象
practice_2_26();
practice_2_27();
practice_2_28();
practice_2_29();
const_test();
constexpr_test();
alias_test();
auto_test();
decltype_test();
return 0;
}
void practice_2_26()
{
//const int buf; //Error const object must be initialized if not extern
int cnt = 0;
const int sz = cnt;
++cnt;
//++sz; //Error cannot assign to a variable that is const
}
void practice_2_27()
{
//int i = -1, &r = 0; //'initializing' : cannot convert from 'int' to 'int &'
const int i = -1, &r = 0;
const int i2 = i;
const int *p1 = &i2;
//int *const p2 = &i2;//'initializing' : cannot convert from 'const int*' to 'int *const'
const int *const p3 = &i2;
}
void practice_2_28()
{
//int i, *const cp; i整型,cp 指向int的 const 指针,必须初始化
//int *p1, *const p2; p1 整型指针,p2 指向int的 const 指针,必须初始化
//const int ic, &r = ic; ic 常量,必须初始化, r 绑定整型常量 ic
//const int *const p3; p3 是一个指向整型常量的常量指针,必须初始化
const int *p; //p指向整型常量
}
void practice_2_29()
{
//i = ic; const int 不能转换为 int
//p1 = p3; const int* const 不能转换为 int *
//p1 = ⁣ const int* 不能赋值给 int *
//p3 = ⁣ p3是个常量,不能改变值
//p2 = p1; p2是个常量,不能改变值
//ic = *p3; ic是个常量,不能改变值
}
void const_test()
{
//const 的引用(reference to const)
//引用类型和所引用对象的类型不一致的特例之一:
//在初始化常量引用时,允许用任意表达式作为初始值,只要能转换成引用的类型即可,比如非常量的对象,字面值,表达式
double dval = 3.14;
const int &ri = dval;
//要保证 ri 所能执行的整数运算,上述代码通过编译器变为
//double dval = 3.14;
//const int temp = dval;
//const int &ri = temp;
//如果 ri 不是一个 const, 则通过 ri 应该可以改变所引用的对象 dval,但实际上 ri 绑定到一个临时量对象上,这种引用显然是无意义的,c++ 就把这种行为归为非法
//指向常量的指针(pointer to const)
//指针类型和所指向对象的类型不一致的特例之一:
//允许令一个指向常量的指针指向一个非常量对象
//所谓的指向常量的指针和引用,不过是指针和引用觉得自己指向常量,自觉不去改变,但所指向的对象可以通过其他途径改变值
//执行对象拷贝时,顶层 const 不受影响,但必须有相同的底层 const 资格
const int v2 = 0;
int v1 = v2, *p1 = &v1, &r1 = v1;
const int *p2 = &v2, *const p3 = &v2, &r2 = v2;
r1 = v2; //v2的顶层 const 被忽略
//p1 = p2; //p2 具有底层 const, p1不具备
p2 = p1;
//p1 = p3; p3 的顶层 const 被忽略,但p1 不具备底层 const
p2 = p3;//p3 的顶层 const 被忽略,并且和 p2 具备底层 const
}
void constexpr_test()
{
//常量表达式(const expression),值不会改变并且在编译过程就能得到计算结果的表达式
//c++11 规定,允许将变量声明为 constexpr 类型以便由编译器来检验变量的值是否是一个常量表达式
//字面值类型(literal type),算术类型,指针,引用
//constexpr 的指针初始值必须为 nullptr 或者 0 或者存储在固定地址(定义于函数体外的对象)中的对象
//constexpr 限定符仅对指针有效,对指向对象无关
constexpr int *p = nullptr; //指向整数的常量指针
constexpr const int *p = nullptr; //指向整数常量的常量指针
}
void alias_test()
{
using pstring = char*; //c++11
typedef char * pstring1;//pstring类型相同
const pstring cstr = 0; //指向 char 的常量指针
const pstring1 *ps = 0;//指针,指向一个指向char的常量指针
}
void auto_test()
{
//c++11 引入 auto 类型说明符,让编译器去分析表达式类型
//定义 auto 引用时,顶层 const 保留,其他类型只保留底层 const
//2.35
const int i = 42;
std::cout << "type" << " i " << typeid(i).name() << std::endl;
auto j = i; //int
std::cout << "type" << " j " << typeid(i).name() << std::endl;
const auto &k = i; //const int&
std::cout << "type" << " i " << typeid(k).name() << std::endl;
auto *p = &i; //const int*
std::cout << "type" << " i " << typeid(p).name() << std::endl;
const auto j2 = i; //const int
std::cout << "type" << " i " << typeid(j2).name() << std::endl;
const auto &k2 = i; //const int
std::cout << "type" << " i " << typeid(k2).name() << std::endl;
}
void decltype_test()
{
//decltype返回变量和表达式的类型,包括 const 和 引用
const int i = 0, &r = i;
decltype(i) x = 0; //x const int
decltype(r) y = 0; //y const int&
//decltype(r) z; //z const int& 必须初始化
//如果表达式是一个解引用操作,decltype 返回引用类型
int j = 0, *p = &j, &r1 = j;
decltype(r1 + 0) h; //a int,r1 + 0的结果是 int
//decltype(*p) k; //b int& 必须初始化
//如果为变量增加一层括号,将得到引用
decltype(j) l; // c int
decltype((j)) m = j ;// int &,必须初始化
//2.36
int a = 3, b = 4;
decltype(a) c = a; // c int
decltype((b)) d = a; // d int&, (b) 不被视为变量,而是一个表达式
++c; //a = 3, b = 4, c = 4, d = 3
std::cout << a << b << c << d << std::endl;
++d; //a = 4, b = 4, c = 4, d = 4
std:: cout << a << b << c << d << std::endl;
//2.37
//赋值是一类产生引用的表达式,其引用的类型为左值的类型
decltype(a = b) e = a; //e int &
}