底层const与顶层const
顶层const指的是被修饰变量本身无法改变,底层const指的是通过限制指针或者限制引用更改内容的const
通过以下代码来说明
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 
 | void test1(){
 int n = 1;
 int m = 2;
 int *const p1 = &n;
 const int * p2 = &n;
 
 
 (*p1)+=2;
 std::cout<<n<<'\n';
 
 
 
 p2=&m;
 
 m+=50;
 std::cout<<*p2<<'\n';
 
 
 int *p3 = p1;
 const int * p4 = p1;
 
 
 const int *p6 = p2;
 }
 
 void test2()
 {
 
 std::vector<int> v;
 for(int i=1;i<=10;i++) v.push_back(i);
 const std::vector<int>::iterator it1 = v.begin();
 
 *it1 = 10;
 
 for(auto u:v) std::cout<<u<<" ";
 std::cout<<'\n';
 
 std::vector<int>::const_iterator it2 = v.begin();
 
 it2++;
 std::cout<<*it2<<'\n';
 for(auto u:v) std::cout<<u<<" ";
 std::cout<<'\n';
 }
 
 struct mmm{
 int a,b;
 bool operator <(const mmm &c)
 
 
 const {
 return a<c.a;
 }
 };
 
 void test3()
 {
 std::priority_queue<mmm> q;
 q.push(mmm{1,2});
 }
 
 | 
Template
首先 template <typename T> 声明一个为 T 的模板。
Function Template
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 
 | template <typename T>
 const T Add(const T &a,const T &b)
 {
 return a+b;
 }
 
 int main()
 {
 double a=1.1,b=1.9;
 int result1=Add<int>(a,b);
 int result2=Add<double>(a,b);
 a=3.3,b=5.5;
 int result3=Add<double>(a,b);
 std::cout<<result1<<" "<<result2<<" "<<result3<<'\n';
 
 }
 
 | 
Class Template
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 
 | #include<bits/stdc++.h>
 template <typename T>
 class MMM{
 private:
 T num1,num2;
 public:
 MMM(T a,T b):num1(a),num2(b){}
 T add();
 };
 
 template <typename T>
 T MMM<T>::add()
 {
 return num1+num2;
 }
 
 
 int main()
 {
 MMM<decltype(5.2)> a(5.2,5.5);
 std::cout<<a.add()<<'\n';
 }
 
 | 
原始字符串
由于有些时候\n并不是表示换行,以及我们的目的不是输出其他的特殊字符,因此可能会用到原始字符串来表示这个字符串
而使用方法为 R"xxx(str)xxx" xxx为任意门描述性词语,str为我们的字符串,开头和结尾的 xxx 必须一致。
另外 \ 也可以用 \\ 表示,但是总有特殊情况,还是得用原始字符串
reference
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 
 | int main(){
 std::string s = "M:\nexo\ncmmm";
 std::cout<<s<<'\n';
 s = R"/description(M:\nexo\ncmmm)/description";
 std::cout<<s<<'\n';
 
 
 
 
 
 
 }
 
 | 
nullptr
C++ 中 NULL 可能会被 define 为 0,在 CPP 中,最好把 NULL 改成 nullptr (会自动类型转换),但是有的编译器会有 define 成 nullptr
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 
 | void f(int *p){
 std::cout<<"*p\n";
 }
 
 void f(int p)
 {
 std::cout<<"p\n";
 }
 
 int main()
 {
 int *p1=NULL;
 int *p2=nullptr;
 int *p4=p2;
 
 
 
 
 }
 
 | 
CPP ref上面的Possible implementation
| 12
 3
 
 | #define NULL 0
 #define NULL nullptr
 
 | 
常量表达式 constexpr
定义常量
虽然 G++ 允许变量作为数组长度,但是你不能只用G++
constexpr 方便区分是不是真常量,例如 f(const int x) 这里的 x 实际上不是真的常量,可以视作只读的变量
对于 CPP 内置的数据可以直接用constexpr修饰,但是对于自定义的 struct 以及 class,需要这样写:
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | struct MMM{int id,rk;
 };
 
 int main()
 {
 constexpr MMM t{1,2};
 std::cout<<t.id<<" "<<t.rk<<'\n';
 }
 
 | 
修饰函数
函数必须有返回值,并且函数必须返回一个常量。声明和定义都必须在要调用的函数前面。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 
 | constexpr int func(){
 
 
 constexpr int a =100;
 return a;
 }
 
 template<typename T>
 constexpr T mmm(T t)
 {
 return t;
 
 }
 
 struct m3{
 const int id;
 int rk;
 constexpr m3(const int _id,int _rk) : id(_id),rk(_rk)
 {
 }
 
 };
 
 int main()
 {
 constexpr MMM t{1,2};
 constexpr m3 mm(14,2);
 }
 
 | 
auto
auto a= xx ,xx 必须为常量