One Day
-
C++模板的作用
将算法与具体对象分离,与类型无关,通用,节省精力
-
模板的偏特化
模板分成类模板和函数模板,特化分为全特化与偏特化。全特化就是限定死模板实现的具体类型,而偏特化就是如果这个模板有多个类型,那么就只限定其中的一部分。对于函数模板却只有全特化,不能偏特化。
-
Volatile的含义
由于变量可能在编译器的控制或者监控之外发生改变,使用Volatile就会告诉编译器不要优化该变量。如被系统时钟更新的变量。
-
OFFSETOF(s, m)的宏定义,s是结构类型,m是s的成员,求m在s中的偏移量
#define OFFSETOF(TYPE, MEMBER) size_t(&((TYPE*)0)->MEMBER)
-
C++虚函数的实现过程
实现机制: 为每个类对象添加一个隐藏成员,隐藏成员中保存了一个指向函数地址数组的指针,称为虚表指针(vptr),这种数组称为虚函数表(virtual function table, vtbl),即,每个类使用一个虚函数表,每个类对象用一个虚表指针。如果派生类重写了基类的虚方法,该派生类虚函数表将保存重写的虚函数的地址,而不是基类的虚函数地址。如果基类中的虚方法没有在派生类中重写,那么派生类将继承基类中的虚方法,而且派生类中虚函数表将保存基类中未被重写的虚函数的地址。
-
C++虚函数的作用
虚函数作用是实现多态。另外,更重要的是实现封装,使得使用者不需要关注实现的细节。
在很多设计模式中都是这样用法,例如Factory、Bridge、Strategy模式。
-
给出float与“零值”比较的 if 语句(假设变量名为var)?
const float EPSINON = 0.00001;
if ((x >= - EPSINON) && (x <= EPSINON)
...
-
C++类中数据成员初始化顺序?
初始化的顺序:
- 基类的静态变量或全局变量
- 派生类的静态变量或全局变量
- 基类的成员变量
- 派生类的成员变量
初始化的一些规则:
-
成员变量在使用初始化列表初始化时,与构造函数中初始化成员列表的顺序无关,只与定义成员变量的顺序有关。
-
如果不使用初始化列表初始化,在构造函数内初始化时,此时与成员变量在构造函数中的位置有关。
-
类中const成员常量必须在构造函数初始化列表中初始化。
-
类中static成员变量,只能在类内外初始化(同一类的所有实例共享静态成员变量)。
智能指针循环引用
解决循环引用的办法:
1.使用弱引用的智能指针(weak_ptr)打破这种循环引用
2.当parent的生存期超过children的生成期的时候,children改为使用一个普通指针指向parent
3.当只剩下最后一个引用的时候需要手动打破循环引用来释放对象
2 3方法需要程序员手动控制,麻烦且容易出错。使用弱引用智能指针weak_ptr:弱引用计数不会影响对象是否析构,对象的析构由强引用计数决定,即shared_ptr。如果强引用计数不为0,就算弱引用计数为0,对象也不会析构;如果强引用计数为0,就算弱引用计数不为0,对象也会析构。
class B;
class A
{
public:
A()
{
std::cout << "A ctr" << std::endl;
}
~A()
{
std::cout << "A dtr" << std::endl;
}
std::weak_ptr<B> pb;
};
class B
{
public:
B()
{
std::cout << "B ctr" << std::endl;
}
~B()
{
std::cout << "B dtr" << std::endl;
}
std::weak_ptr<A> pa;
};
int main()
{
std::shared_ptr<A> a(new A);
std::shared_ptr<B> b(new B);
a->pb = b;
b->pa = a;
std::cout << "A use count: " << a.use_count() << std::endl;
std::cout << "B use count: " << b.use_count() << std::endl;
}