● 定义数据时,不能使用运行才能确定的大小。
const int arraySize = 3;
int arr[arraySize];
● char ch[6] = “daniel”; //error:Deniel is 7 elements
● 不允许数组直接复制和赋值。
int ia = {0,1,2};
int ia2[](ia); //error:array of ints
● 数组下标的正确类型是size_t
● string *sp1,sp2; //sp1 is a pointer to string,ps2 is a string
string *sp1,*sp2; //both sp1 and sp2 are pointers to string
● 避免使用未初始化的指针。 int *pi = NULL;
● C++提供了一种特殊的指针类型void*,它可以保存任何类型对象地址。不允许使用void*指针操纵它所指向的对象。
● 引用和指针的比较:
1.引用总是指向某个对象:定义引用没有初始化是错误的。
2.给引用赋值修改的是该引用所关联的对象的值,而不是使引用与另一个对象关联。
PS:
int ival = 1024,ival = 2048;
int *pi = &ival, *pi2 = &ival2;
pi = pi2;
pi所指向的对象的值不变,但是指向了另一个不同的对象。
int &ri = ival, &ri2 = ival2;
ri = ri2;
这个赋值操作修改了ri引用的值,而不是引用本身。赋值后这两个引用还是分别指向原来关联的对象,此时这两个对象的值相等。
● 指向指针的指针: int ival = 1024; int *p1 = &ival; int **p2 = &p1;
● 指针访问数据:
int ia[] = {0,2,4,6,8};
int *ip = ia; //ip opints to ia[0]
int *ip2 = ip + 4; //ip2 points to ia[4];
ptrdiff_t n = ip2 – ip;
int last = *(ia+4); //last = 8;
last = *ia + 4; //last = 4;
int ia[] = {0,2,4,6,8};
int *p = &ia[2];
int k = p[-2]; //k = ia[0];
for(int *pbegin = ia, *pend = ia + arrSz; pbegin != pend; ++pbegin)
● C++语言强制要求指向const对象的指针也必须具有const特征,不能使用指向const对象的指针修改基础对象,指向const的指针(自认为指向const的指针,可以不指向const对象,但也不能修改对象的值);
const double *cptr;
const指针。 (指针本身的值不能修改)
int errNum = 0;
int *const curErr = &errNum;
指向const对象的const指针:
const double pi = 3.1415926;
const double *const ptr = π
不能修改指针本身,也不不能修改指针指向的对象的值。
typedef string *pstring;
const pstring cstr;
cstr是指向string类型的const指针。
string *const cstr;
而不是const string *cstr;因为const修饰的是pstring,它是一个指针。
● C风格字符串的标准库函数
strlen(s) // 返回s的长度,不包括字符串结束符null
strcmp(s1, s2) //当s1<s2时,返回值<0 ,当s1=s2时,返回值=0 ,当s1>s2时,返回值>0
strcat(s1, s2) // 将字符串s2连接到s1后,并返回s1
strcpy(s1, s2) // 将s2复制给s1,并返回s1
strncat(s1, s2, n) // 将s2的前n个字符连接到s1后面,并返回s1
strncpy(s1, s2, n) // 将s2的前n个字符复制给s1,并返回s1
char str[16+18+2];
strncpy(str,cp1,17);
strncpy(str,” ”,2);
strncpy(str,cp2,19);
● 创建动态数组:
int *pia = new int[10]; //没有初始化
int *pia = new int[10](); //调用默认构造函数初始化
const int *pia = new const int[10]]();
const string *pis = new const string[10];
size_t n = getSize();
int *p = new int[n];
char arr[0]; //error: cannot define zero-length array
char *cp = new char[0]; //ok:but cp cannot be dereferenced
delete []pia;
● string str(“hello world”);
const char *str2 = str.c_str(); //返回C风格字符串
vector<int> ivec(int数组名,数组名+数组大小);
● int ia[3][4];
int (*ip)[4] = ia; //ip points to an array of 4 ints;
ip = &ia[2]; //ia[2] is an array of 4 ints;
int *ip[4]; //array of points to int;
int (*p)[4]; //points to an array of 4 ints
typedef int arr[4];
arr *ip = ia;
● 如果两个操作数为正,除法和求模操作的结果也是正数;如果两个操作数为负,除法操作的结果为正数,而求模操作的结果为负数。如果只有一个操作数为负数,这两种操作的结果取决于机器;求模结果的符号也取决于机器,而除法操作的值则是负数或0.
● 逻辑与和逻辑或操作符总是先计算其左操作数,然后再计算其右操作数。只有在仅靠左操作数的值无法确定该逻辑表达式的结果时,才会求解其右操作数。我们常称这种求值策略为“短路求值”。
● if(i < j <k) {} 这种只要k大于1就为true。(i < j)返回0或1
if(i < j && j < k) {} 这种才能求得正确的结果
● 左移操作符(<<)在右边插入0以补充空位。对于右移操作符(>>),如果其操作数是无符号数,则从左边开始插入0,如果操作 数是有符号数,则插入符号位的副本或者0。
● cout<<(10 < 40); //print 1
cout<<10 < 40 //error
int ival, jval;
ival = jval = 0;
● 为了防止手误,我们用if(42 == i)代替if(i == 42) .因为if(i = 42) 不同于与 if(i == 42)
● 因为前置操作需要做的工作更少,只需加1后返回加1后的结果即可。而后置操作符必须先保存操作符原来的值,以便返回未加1之前的值作为操作的结果。因此,养成使用前置操作这个好习惯,就不必担心性能差异的问题。
● sizeof操作符的作用是返回一个对象或类型名的长度,返回值的类型为size_t
1.对 char类型或值为char类型的表达式做sizeof操作保证得1。
2.对引用类型做sizeof操作将返回存放此引用类型对象所需的内存空间大小。
3.对指针做sizeof操作将返回存放指针所需的内存大小;注意,如果要获取该指针所指向对象的大小,则必须对指针进行解引用。
4.对数组做sizeof操作等效于将对元素类型做sizeof操作的结果乘以数组元素的个数。int sz = sizeof(ia) / sizeof(*ia);
● C++操作符的优先级
● 求值顺序:
if(ia[index++] < ia[index]) //C++语言不能确保从左到右的计算次序,所以有两种情况 index = 0
if(ia[0] < ia[0]) 或 if(ia[0] < ia[1])
● int *pi = new int; //pi points to an uninitialized int
int *pi = new int(); //pi points to an int value-initialized to 0
如果指针指向不是new分配的内存地址,则在该指针上使用delete是不合法的。
一旦删除了指针所指向的对象,立即将指针置为0.
● 显式转换:
static_cast、dynamic_cast、const_cast、reinterpret_cast
dynamic_cast 支持运行时识别指针或引用所指向的对象。
const_cast 将转换掉表达式的const性质。转换掉!
static_cast 编译器隐式执行的任何类型转换都可以由static_cast显式完成。
reinterpret_cast 通常为操作数的位模式提供较低层次的重新解释。
应该避免使用强制类型转换。
● 空语句也是一个语句。
ival = v1 + v2;; 一条表达式语句,一条空语句
● 存在一个普遍的误解:以为程序只会执行匹配的case标号相关联的语句。实际上程序从该点开始执行,并跨越case边界继续执行其他语句,直到switch结束或遇到break语句为止。
● 对于switch结构,只能在它的最后一个case标号或default标号后面定义变量:
如果在两个case标号之间定义变量,该变量会在块结束之前一直存在,对于定义该变量的标号后面的其他case标号,他们所关联的代码都可以使用这个变量。如果switch从那些后续case标号开始执行,那么这个变量可能还未定义就要使用了。
在这种情况下,如果需要为某个特殊的case定义变量,则可以引入语句块,在该块语句中定义变量,从而保证这个变量在使用前被定义和初始化。
case true:
{
string fileName;
……….
}
● 在for语句头定义的任何对象只限制在for循环体里可见。
● 标准异常类
● assert断言
如果为false,assert输出信息,并且终止程序的执行。如果为true,则不采取任何操作。
这篇结束~~~
BY:AloneMonkey