【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>
1 如果出于某些原因,需要在const成员函数中修改某一个或几个成员,那么可以将需要修改的成员声明为mutable,例如
class A
{
public:
int m_cannotBeModified;
mutable int m_needToBeModified;
void ModifyMutable() const
{
m_needToBeModified = 1; //合法
m_cannotBeModified = 1; //不合法
}
};
2 如果一个类没有显式声明构造函数,拷贝构造函数,赋值运算符,析构函数,编译器会相应地合成一个,如果类显式定 义了任何一个构造函数,包括拷贝构造函数,编译器就不会再合成构造函数。
3 要阻止一个类对象拷贝或赋值,可以声明一个简单的基类,基类中将拷贝构造函数和赋值运算符声明为private,这样其派生类的拷贝或赋值操作在编译期就可以被检查出来。例如:
class A
{
protected:
A(){}
~A(){}
private:
A(const A& a){}
A& operator=(const A&a){}
};
class B : public A
{
};
int main()
{
B b;
//B b1(b); //编译不通过
//B b2 = b; //编译不通过
B b3;
//b3 = b; //编译不通过
return 0;
}
如果B不继承自任何类,直接把其拷贝构造函数和赋值运算符声明为private,并定义,那么类外不能做拷贝或赋值操作, 类内部或友元函数或友元类仍可做拷贝或赋值操作。
如果B不继承自任何类,直接把其拷贝构造函数和赋值运算符声明为private,不提供定义,那么类外不能做拷贝或赋值操作,类内部或友元函数或友元类要做拷贝或赋值操作的话,链接期会发现错误,因为没有提供定义。
4 如果在基类的构造函数中调用虚函数,那么虚函数绝不会下降到派生类阶层,调用的仍是基类本身的虚函数,这时虚函数并没有表现得像虚函数。派生类对象在基类构造期间,其对象类型就是基类,其运行时类型信息也属于基类,在进入派生类构造函数前绝不会成一个派生类对象。
5 使用引用计数型智能指针shared_ptr可以有效管理资源,但如果使用shared_ptr时出现了环状引用,还是会导致内存泄露例如下面的代码,程序退出后,new出来的A和new出来的B的引用计数都仍然是1,堆上的内存空间都不会释放。
class B;
class A
{
public:
shared_ptr<B> m_b;
};
class B
{
public:
shared_ptr<A> m_a;
};
int main()
{
shared_ptr<A> a(new A); //new出来的A的引用计数此时为1
shared_ptr<B> b(new B); //new出来的B的引用计数此时为1
a->m_b = b; //B的引用计数增加为2
b->m_a = a; //A的引用计数增加为2
}
再例如下面的代码,主函数退出后,new出来的CCycleRef引用计数为1,内存无法释放:
class CCycleRef
{
public:
~CCycleRef()
{
cout <<"destroying CCycleRef"<<endl;
}
public:
shared_ptr<CCycleRef> selfRef;
};
void CycleRefTest()
{
shared_ptr<CCycleRef> cyclRef(new CCycleRef());
cyclRef->selfRef = cyclRef;
}
int _tmain(int argc, _TCHAR* argv[])
{
CycleRefTest();
return 0;
}
解决办法是使用弱智能指针定义类中的智能指针成员,即将类中的shared_ptr换成weak_ptr即可。
6 前置自增运算符返回的是操作数加1后的值,返回的是操作数本身,是一个左值后置自增运算符返回的是操作数加1前的值,其操作数可以理解为值与原操作数相等的一个常量,是一个右值。
重载前自增运算符和后自增运算符时,要保证其语义与全局的前自增运算符和后自增运算符的语义相同,即前自增返回一个左值,后自增返回一个右值。所以重载的前自增运算符通常返回该对象的引用,以支持++++obj这样的操作;重载的后自增运算符通常返回该类的一个常量对象,防止出现obj++++这样的操作。
例如下面的代码:
class A
{
public:
A(){ m_num = 0; }
A& operator++()
{
++m_num;
return *this;
}
const A operator++(int i)
{
A temp(*this);
++*this;
return temp;
}
public:
int m_num;
};
来源:oschina
链接:https://my.oschina.net/u/2420118/blog/664605