今天又拿出尘封已久的BJ的The C++ Programming Language翻了翻,发现了一些容易被忽视、遗忘但有很重要的细节,记录在这里算是一个备忘吧。
- 从pointer到bool类型之间存在implicit conversion。bool至少和char占用空间相同。
- 一个char 8位字符的value是从0到255还是从-127到+127是implementation-defined。但从0到127这部分是相同的。为了保证可移植性,赋值时尽量避免使用整型数值。
- Enumerator range。 每个enumerator的value都存在一个range。如果对其初始化或赋值时超出了这个range,结果是undefined。因此从integer到enumeration之间必须是explicit conversion。为了保证可移植性,要避免赋integral value时超出range的情况发生。Range的确定方法见p.77.
- 一个hidden global name可以通过::来引用,一个hidden local name无法被引用。
- string literal 的类型是const char[n+1],n是字符个数。例如,"hello" 的类型是 const char[6]。在从前版本C/C++中,string literal的类型是char*,为了兼顾从前的大量程序,把一个string literal赋值给char*依然有效,但是修改const 字串的结果是undefined。例如,char* pstr="hello"; pstr[1]='t';
- 从一个函数中返回string literal是安全的,因为给string literal分配的空间不会因为函数的返回而被释放。例如,return "hello";
- 两个完全相同的string literal 是否只有一份copy,是implementation-defined. 例如,char* pstr1 = "hello"; char* pstr2="hello"; pstr1是否等于pstr2由具体实现决定的。
- 两个指针相减只有在他们指向同一个数组时,结果才被defined。指针相加没有意义、不被允许。
- "plain" T&类型的initializer必须是Lvalue,const T&类型的initializer不必是Lvalue甚至不必是类型T(存在implicit type conversion)。例如,int& i = 1;(error) const int& i = 1; (OK,产生的临时变量一直存在知道i的scope结束)。
- pointers to function,pointers to members不能赋值给void*
- structure对象的大小未必是其member大小之和。

谢谢,很有用。原先只知道3、4、5、6这几点,7可能跟编译器的优化程度也有点关系,1和2仍然不是很明白。
关于11点,我曾经测试过,如果
struct A {};
cout
在Windows下为1,Linux下为0,呵呵,如果结构被对齐过,则值又不同了。
http://blog.ipattern.org/archives/281