总结一些C++学习中疑惑的点
知识点
const和指针
1 2 3 4
| const double pi=3.14; const double *p=π double dval=3.14; p=&dval;
|
存放常量对象的地址必须要使用指向常量的指针,
但是指向常量的指针也可以指向变量
- const指针:常量指针必须初始化,常量指针指向的对象地址不可改变。
1 2 3 4
| int a=0; int *const p=&a; const doublie pi=3.14; const double *const pip=π
|
- 顶层const:表示指针本身是个常量
- 底层const: 表示所指的对象是个常量
指针指向对象,指针在顶层,对象在底层。
1 2 3 4 5
| int v1=0; int *p1=&v1; const int *p2=p1; p1=p2;
|
当执行对象拷贝时,拷入拷出的对象必须具有相同的底层const资格。或者两个对象数据类型必须可以转换。非常量可以转换成常量,反之不行
底层指针的拷入主要看是否同为底层的或者是非常量。
常量指针的拷入只能拷入常量。
顶层指针因为只能初始化一次后不能改变所以不做讨论。
constexpr
1 2
| const int *p=nullptr; constexpr int *q=nullptr;
|
数组
引用遍历法:
要使用范围for语句处理多维数组,除了最内层的循环外,其他所有循环的控制变量都应该是引用类型。
1 2 3 4 5 6
| int ia[row][col]; for(auto &row:ia){ for(auto i:row){ cout << i; } }
|
但是想要去更改数组里面的值就要使用引用类型去遍历
1 2 3 4 5
| for(auto &row:ia){ for(auto &col:row){ } }
|
下标遍历法:
1 2 3 4 5 6
| int ia[row][col]; for(size_t i=0;i!=row;++i){ for(size_t j=0;j!=col;++j){ ia[i][j]=1; } }
|
指针遍历法:
1 2 3 4 5
| for(auto p=ia;p!=ia+3;++p){ for(auto q=*p;q!=*p+4;++q){ ... } }
|
其中p中存放地址是ia[x]的地址而且ia[x]和ia[x+1]的地址是连续的,而*p是取ia[x][0]的地址。
左值和右值
拷贝构造函数
如果一个构造函数的第一个参数是自身类类型的引用,且任何额外参数都有默认值,则此构造函数是拷贝构造函数。当使用拷贝初始化时,我们会用到拷贝构造函数。
1 2 3 4 5
| class Foo{ public: Foo(); Foo(const Foo&); }
|
拷贝函数通常不应该是explicit的
拷贝初始化
重载拷贝赋值运算符
如果一个类未定义自己的拷贝赋值运算符,编译器会为它生成一个合成拷贝赋值运算符
如果一个运算符是一个成员函数,其左侧运算对象就绑定到隐式的this参数。赋值运算符通常返回一个指向其左侧运算对象的引用。
练习
9.43
如果使用!=来比较两个迭代器在这题是不行的,但是如果不是特殊条件最好写成!=的判断条件。
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
| #include <iostream> using namespace std;
void replace(string& s, const string& oldVal, const string& newVal) { auto curr = s.begin(); while (curr <= s.end() - oldVal.size()) { if (oldVal == s.substr(curr-begin(s), oldVal.size())) { curr = s.erase(curr, curr + oldVal.size()); curr = s.insert(curr, newVal.begin(), newVal.end()); curr += newVal.size(); } else { ++curr; } } } int main() { string s = "tho "; string oldVal = "tho"; string newVal = "though"; replace(s, oldVal, newVal); cout << s; return 0; }
|
9.44
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #include <iostream> using namespace std;
void replace(string& s, const string& o, const string& n) { size_t i = 0; while (i+o.size() <= s.size()) { if (o == s.substr(i,i+o.size())) { s.replace(i, o.size(), n); i += n.size(); } else { i++; } } } int main() { string s = "tho "; string oldVal = "tho"; string newVal = "though"; replace(s, oldVal, newVal); cout << s; return 0; }
|