底层const与顶层const
顶层const指的是被修饰变量本身无法改变,底层const指的是通过限制指针或者限制引用更改内容的const
通过以下代码来说明
1 2 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
1 2 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
1 2 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
1 2 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
1 2 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
1 2 3
| #define NULL 0
#define NULL nullptr
|
常量表达式 constexpr
定义常量
虽然 G++ 允许变量作为数组长度,但是你不能只用G++
constexpr
方便区分是不是真常量,例如 f(const int x)
这里的 x
实际上不是真的常量,可以视作只读的变量
对于 CPP 内置的数据可以直接用constexpr修饰,但是对于自定义的 struct
以及 class
,需要这样写:
1 2 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'; }
|
修饰函数
函数必须有返回值,并且函数必须返回一个常量。声明和定义都必须在要调用的函数前面。
1 2 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
必须为常量