@gump88
2016-08-13T20:47:58.000000Z
字数 3822
阅读 1109
title: Tips From C++ Primer
date: 2016-06-06 20:31:12
C++
2 const引用是指向const对象的引用,可以读取但是不能修改。
const int ival = 100;
const int &refi = ival;
int &refi2 = ival; //wrong
const vector<int> nines = (10,9);
//error,cit2是一个常量迭代器,自己的值不可以改变,但是可能改变迭代器指向的值
const vector<int> :: iterator cit2 = nines.begin();
//const_iterator表明指向的值不可以改变,但是迭代器的值可以改变
vector<int> ::const_iterator it = nines.begin();
//error
*it = 10;
//correct
++it;
string st3("Hello world!");
char *str = st3;//compile error
const char *str = st3.c_str();//success,这里st3.c_str()返回的是const char类型的数组,避免修改该数组。
int ia[3][4];
int (*ip)[4] = ia;//表明是一个指向4个int类型数组的指针
ip = &ia[2]; //重新指向第三个int型数组ia[2]
//注意下面的写法表示的意义是不一样的
int *ip[4]; //表明ip指向一个int 型指针数组,array of pointers to int
int (*ip)[4]; //表明ip指向一个int 型数组,pointer to an array of 4 ints
vector<int> ivec;
vector<int>::iterator iter = ivec.begin();
while(iter != ivec.end())
cout<<*iter++<<endl;
解引用操作的优先级低于后自增操作,所以上述表达式先后++,然后进行解引用。
后自增的优先级高于前自增,点操作的优先级高于解引用操作优先级
13 默认实参
14 内联函数
15 关键字static
非static数据成员存在于类类型的每个对象中,static数据成员独立于该类的任意对象而存在;每个static数据成员是与类关联的对象,并不与该类的对象相关联。
static成员函数没有this形参,他可以直接访问所属类的static成员,但是不能直接使用非static成员。
16 构造函数和析构函数是否可以为虚函数。构造函数不能为虚函数,但是析构函数可以且常常是虚函数。 简单解释:构造函数如果设为虚函数,那么在对象初始化时,需要通过虚表vtable去取这个构造函数,这就存在一个矛盾,因为这时对象并没有初始化。但是,析构函数可以是虚函数,且常常如此,因为此时vtable已经初始化了;而且我们常常通过基类的指针来销毁对象,如果析构函数不为虚的话,就不能正确识别对象类型,因此析构函数常常设为虚函数。
17 C/C++程序编译的程序占用的内存类型:
18 虚函数的实现:每个类会维护一个虚函数表,类的每个实例会拥有一个虚表指针,通过这个指针可以找到类的虚表。类的虚表中存放的是对应的虚函数地址,通过访问这个地址就可以使用具体的虚函数。
19 volatile关键字
volatile本意是易变的,因为访问寄存器比访问内存单元快得多,编译器会对内存读取进行优化,减少访问内存次数,但这时会出现读取脏数据问题。
因此当一个变量申明为volatile时,表明这个变量是易变的,编译器就不会对该变量的内存读取进行优化,而是总是从内存中读取数据,避免了读取脏数据问题。
20 sizeof和strlen区别
strlen参数是char*,sizeof会计算对象实际占用的内存字节数,如果sizeof作用指针,不管指针指向什么类型,在32位系统上返回值都是4;
具体例子可以参考这个blog。
21 预处理指令
宏定义
条件编译
文件包含
文件包含时为了解决多次包含同一个头文件,降低编译效率的问题,使用了条件编译 + 宏的方法。
22 条件编译
#if 条件成立
...
#elif 条件成立
..
#else 否则条件成立
...
#endif 结束条件编译
判断是否定义过宏
#if defined(MACRO1)
...
#if !defined(MACRO2)
...
#endif
还可以使用下面的定义,实现功能等效上面
#ifdef MACRO
...
#ifndef MACRO
...
#endif
23 结构体作为函数参数进行传递时,其实是将实参中成员的值一一复制给对应形参结构体中的成员。因此,形参的改变不会影响到实参。
24 typeof和#define的区别
typeof是给变量起个别名,#define只是简单的字符串替换,见下面的例子:
#define String1 char*
typedef char *String2;
String1 str1,str2;//等价于
char *str1;
char *str2;
String2 str1,str2;//等价于
char *str1,str2;//等价于
char *str1;
char str2;
25 字符串输出函数puts()和字符串输入gets()函数
puts()函数一次只能输出一个字符串,printf函数一次可以同时输出多个字符串;
gets()函数一次只能读取一个字符串,scanf则可以同时读取多个字符串;
gets函数可以读取包含空格、tab的字符串,直到遇到回车为止;scanf不能用来读取空格、tab;
26 字符输出函数putchar()和字符输入函数getchar()函数
putchar()一次只能输出一个字符,而printf可以同时输出多个字符;
getchar()函数可以读入空格、tab,scanf不能读入空格和tab;
getchar()函数一次只能读入一个字符,scanf则可以同时读入多个字符;
27 字符串函数
strcmp(s2,s1)函数两个字符串从左到右逐个比较,直到遇到字符不相同或者遇见'\0'为止,如果相同返回值为0,如果不相同返回第一个不相同字符的ASCII码值之差;
28 逗号表达式的值是最后一个表达式的值
int a = 1,b = 2,c = 3;
int a = a + b, a + c;
cout<<a<<endl;
//输出是5
29 C语言中动态内存分配
malloc calloc relloc free
30 C++类型转换
dynamic_cast <new_type> (expression)
reinterpret_cast <new_type> (expression)
static_cast <new_type> (expression)
const_cast <new_type> (expression)
31 C++异常处理
32 C++模板