C++拾遗

                                      C++拾遗

转自:http://civilnet.cn/blog/article/610#more-610


1、类的静态函数不能访问非静态数据;



原因:因为静态成员函数不传递this指针, 不和具体实例关联, 所以不能访问非静态member, 多用于callback。


2、类的静态函数不能声明为const、volatile、virtual;


static没有this指针,而这些的实现要求有this指针。


3、类的const成员函数不能改变对象的普通数据成员,但可以改变static和mutable的数据成员。


4、const对象只能调用const成员函数。


5、const可以用作函数重载的依据之一,和参数类型、返回值类型一样。


6、类的成员函数在调用会插入一个ClassName *Const this指针作为参数;而类的const成员函数在调用的时候会插入const ClassName *Const this指针作为参数。


7、没有指向引用的指针,因为引用并没有开放给外部的地址空间(不像普通的变量)。切记,把引用看作是变量的别名。


8、const引用是指不能通过引用改变变量的值,而非变量的值不能被修改;const 引用可以初始化为不同类型的对象或者初始化为右值(非const引用不可以):


int i=5;
const int &j=i;
i=4;//合法
j=4;//非法!!


———————–


int   x=3;
const int&   r=x; //正确
int&  const  r=x; //未定义,可能被编译器忽略,因为引用本来就是const(初始化后不能重新绑定)


——————–


const int ival = 1024;//ival为const
int &ref2 = ival;//错误!把一个const int 引用为非const类型


—————–


int& a =719;//错误
const int& a = 719;//正确,const引用可以初始化为右值


9、常量指针与指针常量:


char const   *p //指向const字符的指针,这个const字符的值不能改变
const char   *p //同上,也是常量指针                
char * const p  //指针本身是const ,不能改变指针的指向,但可以改变字符的内容,是指针常量


 10、下列四种情况必须使用类的初始化列表:


a、初始化引用(reference)成员;


b、初始化 const 成员;


c、调用基类的构造函数,并且该基类的构造函数有参数时;


d、调用一个类成员的构造函数,并且它有参数时。


同时暗示着,如果有上面的四种情况,那么必须有构造函数来初始化它们。


11、iostream,输入输出流,流(stream)这个单词的意思是:试图说明字符是随着时间顺序生成或消耗的。


 12、与其他变量不同,除非特别说明(extern),在全局作用域声明的 const 变量是具有文件作用域的局部变量。不能被其他文件访问。通过指定 const 为 extern(也即 extern const int a = 4;)可以跨文件作用域。


 13、枚举成员是常量表达式,并且枚举成员值可以是不唯一的:


enum CivilNet
{
  gemfield = 2, //2
  leaflower,//3
  syszux = 3, //3
  civilnet_cn//4
};


14、const char name[8] = “Gemfield”; // error: Gemfield is 9 elements


15、一个数组不能用另外一个数组初始化,也不能将一个数组赋值给另一个数组。


16、指针和 typedef


typedef string *pstring;
const pstring cstr;//string *const cstr而非const string *cstr


17、可使用跟在数组长度后面的一对空圆括号,对数组元素做值初始化:
int *gemfield = new int[10] (); //初始化为0
这种方法在const 对象的动态数组中就有用了:
const int *gemfield= new const int[100]();//必须初始化
不过这样的数组用处不大。


18、数组指针:


int *ip[4]; // 数组里面包含4个指针,指向int
int (*ip)[4]; // 指向一个包含有4个int的数组
注意[]的优先级要高。


19、后自增、自减运算符的优先级:
cout << *iter++ << endl;


由于后自增操作的优先级高于解引用操作,因此 *iter++ 等效于 *(iter++)。子表达式 iter++ 使 iter 加 1,然后返回 iter 原值的副本作为该表达式的结果。因此,解引用操作 * 的操作数是 iter 未加 1 前的副本。
 


20、零值指针的删除:


如果指针的值为 0,则在其上做 delete 操作是合法的,但这样做没有任何意义:


int *ip = 0;
delete ip; // ok


C++ 保证:删除 0 值的指针是安全的。
 


21、c++的强制类型转换:
dynamic_cast//无法正确转换那么会返回一个值是0的指针
const_cast //去掉const性质
static_cast//只使用于表达式的原类型与目标类型相适应的情况
reinterpret_cast //用于替代c中与实现相关的或不安全的强制转换


22、预处理器还定义了其余四种在调试时非常有用的常量:


__FILE__ 文件名


__LINE__ 当前行号


__TIME__ 文件被编译的时间


__DATE__ 文件被编译的日期


23、内联函数应该在头文件中定义,这一点不同于其他函数。


inline 函数可能要在程序中定义不止一次,只要 inline 函数的定义在某个源文件中只出现一次,而且在所有源文件中,其定义必须是完全相同的。把 inline 函数的定义放在头文件中,可以确保在调用函数时所使用的定义是相同的,并且保证在调用点该函数的定义对编译器可见。


24、出现在相同作用域中的两个函数,如果具有相同的名字而形参表不同,则称为重载函数。任何程序都仅有一个 main 函数的实例。main 函数不能重载。


如果两个函数声明的返回类型和形参表完全匹配,则将第二个函数声明视为第一个的重复声明。如果两个函数的形参表完全相同,但返回类型不同,则第二个声明是错误的。


函数不能仅仅基于不同的返回类型而实现重载。


仅当形参是引用或指针时,形参是否为 const 才能实现重载。


25、如果我们碰到复杂的类型声明,该如何解析它?例如:
char (*a[3])(int);
a到底被声明为什么东东?指针?数组?还是函数?分析时,从a 最接近(按运算符优先级)处开始。我们看到a最接近符号是[ ]——注意:*比[ ]的优先级低。a后既然有[ ],那么a是数组,而且是包含3个元素的数组。 那这个数组的每个元素是什么类型呢?a[3]是什么类型?是指针,因为它的前面有*. 由此可知,数组a的元素是指针。光说是指针还不够。对于指针,必须说出它指向的东东是什么类型。它指向的东东是什么,就看*a[3]是什么(a[3]是指针,它指向的东东当然是*a[3])了。继续按优先级观察,我们看到*a[3]后面有小括号,所以可以肯定*a[3]是函数。即数组a的元素是指向函数的指针。指向的是什么类型的函数?这很明显,是入参为int、返回值为char的类型的函数。


26、stringstream 对象的一个常见用法是,需要在多种数据类型之间实现自动格式化时使用该类类型。


int val1 = 512, val2 = 1024;
ostringstream format_message;
format_message << “val1: “<< val1<< “val2: ” << val2;//int->string
istringstream input_istring(format_message.str());
string dump;
input_istring >> dump >> val1 >> dump >> val2;//string->int


27、除了引用类型外,所有内置或复合类型都可用做元素类型。引用不支持一般意义的赋值运算,因此没有元素是引用类型的容器。C++ 语言中,大多数类型都可用作容器的元素类型。容器元素类型必须满足以下两个约束:


元素类型必须支持赋值运算;
元素类型的对象必须可以复制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值