每天花点时间,重新拾起C++,记录一些学习笔记,内容根据自己理解逐步更新。
1.指针
我们最熟悉的,一个字节由8位构成,一个字由32位构成,这是针对32位操作系统,其实字的大小是依赖于机器的,C++基本数据类型,int/short/long/float/double/long double长度都是以字为单位,如short为半个字,int为一个字,double是两个字,具体它们能代表多少位数据,能存储多大范围的值就需要根据操作系统环境而定。
文字常量是不可寻址的,变量可以。根据一个例子学习指针和地址的存储空间变化。
2.字符串
C风格的字符串和标准C++ string类型,前者是作为标准C++一个部分的标准C库,后者是标准C++提供的string类,主要描述C风格的字符串。
字符串为空的定义:
C风格字符串的字符指针总是指向一个相关联的字符数组,通过自增可以前进到终止空字符之后,这个地方容易出错。
可以单独增加一个指针计算st长度
由于字符指针的底层特性,使得用它表示字符串容易出错,因此C++标准库提供了字符串类抽象的一个公共实现,要使用string类型,必须包含头文件
3.const关键字
“试图将一个非const对象的指针指向一个常量对象”的动作都将引起编译错误,const对象的地址只能赋值给指向const对象的指针,但是指向const对象的指针可以被赋以一个非const对象的地址。
注意这三者区别:
这段代码:
如果这样定义就会出错:
定义int*为T,上面的代码等价于:
编译器会这样来处理这段赋值计算:
这里temp是"int *"类型,编译器不能强制把"const int *"转变为"int *"类型,原程序没有问题,是因为编译器这样处理了,定义"const int *"为T:
这样就解决了之前类型不匹配的赋值问题。
4.数组
非const的变量不能被用来指定数组的维数,这是初学C语言时会犯的错误之一。C++不能在编译时刻或运行时刻对数组下标进行范围检查,因此即使程序能够通过编译并执行,但仍可能存在错误。
ia[ 1, 2 ]在C++中是合法的,但"1,2"是一个逗号表达式,因此它等价于ia[2]。
定义数组
ia、&ia[0]是等价的,ia+1、&ia[1]是等价的,可以通过指针实现数组的遍历:
5.vector容器
使用vector需要添加头文件vector,vector有两种不同形式:数组习惯和STL习惯。
数组习惯
vector<int> ivec(10);//与int a[10]类似
STL习惯
vector<string> text;
6.typedef
为内置的或用户定义的数据类型引入助记符号,例如:
typedef可以用来增强“复杂模板声明的定义”的可读性,增强“指向函数的指针”以及“指向类的成员函数的指针”的可读性。
用typedef可以方便地定义大量pair类型的对象:
7.volatile
volatile修饰符的用法和const类似,主要目的是提示编译器,该对象的值可能在编译器未检测到的情况下被改变,因此编译器不能武断的对引用这些对象的代码作优化处理。
参考书籍:《C++ Primer》第三版
1.指针
我们最熟悉的,一个字节由8位构成,一个字由32位构成,这是针对32位操作系统,其实字的大小是依赖于机器的,C++基本数据类型,int/short/long/float/double/long double长度都是以字为单位,如short为半个字,int为一个字,double是两个字,具体它们能代表多少位数据,能存储多大范围的值就需要根据操作系统环境而定。
文字常量是不可寻址的,变量可以。根据一个例子学习指针和地址的存储空间变化。
- #include "iostream"
- using namespace std;
- int _tmain(int argc, _TCHAR* argv[])
- {
- /* ival为整型变量 */
- /* pi指向ival地址 */
- /* ppi指向pi地址,即指针的指针 */
- /* *ppi为pi指针所指向的值 */
- int ival = 1024;
- int *pi = &ival;
- int **ppi = π
- cout << "The value of ival/n"
- << "direct value: " << ival << "/n" //1024
- << "indirect value: " << *pi << "/n" //1024
- << "double indirect value: " << **ppi << "/n" //1024
- << "value of *ppi: " << **ppi << "/n" //1024
- << endl;
- /* pi地址加2个单位,对整形变量而言,地址值增加2×4字节=8 */
- pi = pi + 2;
- cout << pi;
- return 0;
- }
#include "iostream" using namespace std; int _tmain(int argc, _TCHAR* argv[]) { /* ival为整型变量 */ /* pi指向ival地址 */ /* ppi指向pi地址,即指针的指针 */ /* *ppi为pi指针所指向的值 */ int ival = 1024; int *pi = &ival; int **ppi = π cout << "The value of ival/n" << "direct value: " << ival << "/n" //1024 << "indirect value: " << *pi << "/n" //1024 << "double indirect value: " << **ppi << "/n" //1024 << "value of *ppi: " << **ppi << "/n" //1024 << endl; /* pi地址加2个单位,对整形变量而言,地址值增加2×4字节=8 */ pi = pi + 2; cout << pi; return 0; }
2.字符串
C风格的字符串和标准C++ string类型,前者是作为标准C++一个部分的标准C库,后者是标准C++提供的string类,主要描述C风格的字符串。
字符串为空的定义:
- char *pc1 = 0;
- char *pc2 = "";
char *pc1 = 0; char *pc2 = "";
C风格字符串的字符指针总是指向一个相关联的字符数组,通过自增可以前进到终止空字符之后,这个地方容易出错。
- #include "iostream"
- using namespace std;
- const char *st = "The expense of spirit/n";
- int _tmain(int argc, _TCHAR* argv[])
- {
- int len = 0;
- while ( *st++ )
- ++len;
- /* st指针前进到字符串终止空字符之后 */
- /* len长度为字符串长度加1 */
- st = st - len;
- /* 输出内容为"he expense of spirit" */
- cout << len << ": " << st;
- return 0;
- }
#include "iostream" using namespace std; const char *st = "The expense of spirit/n"; int _tmain(int argc, _TCHAR* argv[]) { int len = 0; while ( *st++ ) ++len; /* st指针前进到字符串终止空字符之后 */ /* len长度为字符串长度加1 */ st = st - len; /* 输出内容为"he expense of spirit" */ cout << len << ": " << st; return 0; }
可以单独增加一个指针计算st长度
- const char *p = st;
const char *p = st;
由于字符指针的底层特性,使得用它表示字符串容易出错,因此C++标准库提供了字符串类抽象的一个公共实现,要使用string类型,必须包含头文件
- #include "string"
#include "string"
3.const关键字
“试图将一个非const对象的指针指向一个常量对象”的动作都将引起编译错误,const对象的地址只能赋值给指向const对象的指针,但是指向const对象的指针可以被赋以一个非const对象的地址。
注意这三者区别:
- /* 指向double类型的,定义成const对象的指针 */
- const double *pc = 0;
- const double minWage = 9.60;
- pc = &minWage;
- /* 指向int类型的const指针 */
- int errNumb = 0;
- int *const curErr = &errNumb;
- /* 指向double类型的,定义成const对象的const指针 */
- const double pi = 3.14159;
- const double *const pi_ptr = π
/* 指向double类型的,定义成const对象的指针 */ const double *pc = 0; const double minWage = 9.60; pc = &minWage; /* 指向int类型的const指针 */ int errNumb = 0; int *const curErr = &errNumb; /* 指向double类型的,定义成const对象的const指针 */ const double pi = 3.14159; const double *const pi_ptr = π
这段代码:
- using namespace std;
- const int ival = 1024;
- const int *const &pi_ref = &ival;
- int _tmain(int argc, _TCHAR* argv[])
- {
- return 0;
- }
using namespace std; const int ival = 1024; const int *const &pi_ref = &ival; int _tmain(int argc, _TCHAR* argv[]) { return 0; }
如果这样定义就会出错:
- const int *&pi_ref = &ival;
const int *&pi_ref = &ival;
定义int*为T,上面的代码等价于:
- const T &pi_ref = &ival;
const T &pi_ref = &ival;
编译器会这样来处理这段赋值计算:
- T temp;
- temp = &ival;
- const T &pi_ref = temp;
T temp; temp = &ival; const T &pi_ref = temp;
这里temp是"int *"类型,编译器不能强制把"const int *"转变为"int *"类型,原程序没有问题,是因为编译器这样处理了,定义"const int *"为T:
- T temp;
- temp = &ival;
- T const &pi_ref = temp;
T temp; temp = &ival; T const &pi_ref = temp;
这样就解决了之前类型不匹配的赋值问题。
4.数组
非const的变量不能被用来指定数组的维数,这是初学C语言时会犯的错误之一。C++不能在编译时刻或运行时刻对数组下标进行范围检查,因此即使程序能够通过编译并执行,但仍可能存在错误。
ia[ 1, 2 ]在C++中是合法的,但"1,2"是一个逗号表达式,因此它等价于ia[2]。
定义数组
- int ia[9] = { 0, 1, 1, 2, 3, 5, 8, 13, 21 };
int ia[9] = { 0, 1, 1, 2, 3, 5, 8, 13, 21 };
ia、&ia[0]是等价的,ia+1、&ia[1]是等价的,可以通过指针实现数组的遍历:
- #include "iostream"
- using namespace std;
- int _tmain(int argc, _TCHAR* argv[])
- {
- int ia[9] = { 0, 1, 1, 2, 3, 5, 8, 13, 21 };
- int *pbegin = ia;
- int *pend = ia + 9;
- while ( pbegin != pend ) {
- cout << *pbegin << ' ';
- ++ pbegin;
- }
- return 0;
- }
#include "iostream" using namespace std; int _tmain(int argc, _TCHAR* argv[]) { int ia[9] = { 0, 1, 1, 2, 3, 5, 8, 13, 21 }; int *pbegin = ia; int *pend = ia + 9; while ( pbegin != pend ) { cout << *pbegin << ' '; ++ pbegin; } return 0; }
5.vector容器
使用vector需要添加头文件vector,vector有两种不同形式:数组习惯和STL习惯。
数组习惯
vector<int> ivec(10);//与int a[10]类似
STL习惯
vector<string> text;
6.typedef
为内置的或用户定义的数据类型引入助记符号,例如:
- typedef vector<int> vec_int;
- vec_int vec1(10);//与vector<int> vec1(10);一样
typedef vector<int> vec_int; vec_int vec1(10);//与vector<int> vec1(10);一样
typedef可以用来增强“复杂模板声明的定义”的可读性,增强“指向函数的指针”以及“指向类的成员函数的指针”的可读性。
- /* cstr类型非"const char *" */
- /* const修饰cstr类型,cstr是一个指针 */
- /* cstr是一个指向字符的const指针 */
- typedef char *cstring;
- extern const cstring cstr;
/* cstr类型非"const char *" */ /* const修饰cstr类型,cstr是一个指针 */ /* cstr是一个指向字符的const指针 */ typedef char *cstring; extern const cstring cstr;
用typedef可以方便地定义大量pair类型的对象:
- typedef pair<string, string> Authors;
- Authors joyce("james", "joyce");
- Authors musil("robert", "musil");
- if (joyce.first == "james" && joyce.second == "joyce")
- /* 满足if条件,处理相关任务 */
typedef pair<string, string> Authors; Authors joyce("james", "joyce"); Authors musil("robert", "musil"); if (joyce.first == "james" && joyce.second == "joyce") /* 满足if条件,处理相关任务 */
7.volatile
volatile修饰符的用法和const类似,主要目的是提示编译器,该对象的值可能在编译器未检测到的情况下被改变,因此编译器不能武断的对引用这些对象的代码作优化处理。
参考书籍:《C++ Primer》第三版