记录一下看书的时候自己的一些疑问,有的是书上的解释,有的是书上没有解释,在其他书上或者网络上找的解释,标注为红色的是待解决的问题。
1、为什么要有显式复制构造函数才能触发NRV优化?
cfront编译器有一个开关机制,若检测到没有显式的复制构造函数,则判断程序员对bitwise效率满意,不用进行NRV优化,反之则进行NRV进行优化。Visual c++和g++等编译器已取消这一开关机制。
2、将派生类成员函数的返回值作为基类构造函数的参数,会发生什么?待解决
class FooBar:public X {
int _fval;
public:
int fval(){ return _fval; }
FooBar( int val ): _fval( val ),X( fval() ) {}
};
//为什么转化为以下伪码?
//c++伪码
FooBar::FooBar(/* this pointer */)
{
X::X( this, this->fval() );
_fval = val;
}
3、成员初始化列表的机制?
编译器按照初始化列表中的变量在类中声明顺序进行处理,然后在用户显式代码之前插入这些成员的初始化代码
4、如何取类成员变量偏移地址?
(int)&((class type*)0->data member)
因为并没有对内存进行存取操作,只是借用了编译器的计算地址操作,所以不会报错,如果是(class type*)0->data menber,则会出现运行时异常
而原书上写的&(class type)::data member疑似有误,貌似无法用来求偏移地址,《C++ primer》中说(class type)::data member是用来区分在成员函数中使用的同名参数是来自于“形参”还是“类中成员变量”,即
(class type)::data member 相当于 this->data member
3.6节有对指向data member的指针的详细讨论
5、从“对象”存取成员变量和从“对象指针”存取成员变量有何区别?
正常情况下没有区别,但如果对象类有一个虚基类的时候
对象指针无法在编译期确定虚基类的地址,因为无法确定该指针指向的是哪个类的对象,所以会将确定地址推迟到执行期
但是对象可以,因为一个对象实例在编译期就可以将所有成员变量的地址确定下来
6、虚表的元素中“用于支持runtime type identification”的“一个或两个slots”是什么?待解决
7、vptr放在class的前端和后端有什么区别?
- 把vptr放在类的前端,对于在多重继承下,通过指向class member的指针调用virtual function,会有一些帮助(4.4节)
- 把vptr放在类的后端,可以保留base class C struct的对象布局,但是几乎没有人会从一个C结构体派生出具有多态性质的类
- 把vptr放在类的后端,还多了计算vptr在对象中offset的开销