Professional C++ CH07
文章目录
前言
本章主要介绍类的继承相关内容
Memory Management
1.malloc & new
malloc()函数在c++中仍然存在,但应该避免使用它。new相对于malloc()的主要优点是new不只是分配内存,它还构造对象!
Foo* myFoo = (Foo*)malloc(sizeof(Foo));
Foo* myOtherFoo = new Foo();
在执行这些行之后,myFoo和myOtherFoo都将指向堆上足以容纳Foo对象的内存区域。可以使用这两个指针访问Foo的数据成员和方法。不同之处在于myFoo所指向的Foo对象不是一个正确的对象,因为它从未被构造过。malloc()函数只留出一定大小的内存。它不知道也不关心对象。相反,对new的调用分配适当的内存大小,并调用适当的构造函数来构造对象。
2.堆上和栈上的二维数组
区别:下图一目了然
3.智能指针
3.1 unique_ptr
有时候可能认为代码正确地释放动态分配的内存。不幸的是,它很可能不是在所有情况下都正确。取以下函数:
void couldBeLeaky() {
Simple* mySimplePtr = new Simple(); mySimplePtr->go();
delete mySimplePtr;
}
这个函数动态分配一个Simple对象,使用该对象,然后正确地调用delete。但是,在本例中仍然可能存在内存泄漏!如果go()方法抛出异常,则永远不会执行对delete的调用,从而导致内存泄漏。
在这两种情况下,都应该使用unique_ptr。对象不会被显式删除;但当unique_ptr实例超出作用域(在函数的末尾,或因为抛出了异常)时,它会自动在析构函数中释放Simple对象:
void notLeaky() {
auto mySimpleSmartPtr = make_unique<Simple>(); //C++14
unique_ptr<Simple> mySimpleSmartPtr(new Simple()); //C++11
mySimpleSmartPtr->go();
}
这段代码使用c++ 14中的make_unique(),并结合auto关键字,这样您只需指定指针的类型,在本例中为Simple,只需指定一次。如果Simple构造函数需要参数,则将它们放在make_unique()调用的圆括号之间。
智能指针中,get()方法可用于直接访问底层指针。这对于将指针传递给需要哑指针的函数很有用。例如有以下函数:
void processData(Simple* simple) { /* Use the simple pointer... */ }
auto mySimpleSmartPtr = make_unique<Simple>();
processData(mySimpleSmartPtr.get());
可以释放unique_ptr的基础指针,并使用reset()将其更改为另一个指针。例如:
mySimpleSmartPtr.reset(); // Free resource and set to nullptr
mySimpleSmartPtr.reset(new Simple()); // Free resource and set to a new
// Simple instance
3.1 shared_ptr
双重删除的问题很容易引起。考虑本章前面介绍的Simple类,它在创建和销毁对象时只输出消息。如果要创建两个标准的shared_ptrs,并让它们都引用同一个Simple对象,如下所示,当它们被销毁时,两个智能指针都会尝试删除同一个对象:
void doubleDelete() {
Simple* mySimple = new Simple();
shared_ptr<Simple> smartPtr1(mySimple);
shared_ptr<Simple> smartPtr2(mySimple);
}
// Simple constructor called!
// Simple destructor called!
// Simple destructor called!
调用了两次析构函数。这在unique_ptr中也会遇到同样的问题,即使引用计数的shared_ptr类也会这样做。然而,根据c++标准,这是正确的行为。不应该像前面的doubleDelete()函数那样使用shared_ptr来创建两个指向同一个对象的shared_ptrs。相反,你应该拷贝一份如下:
void noDoubleDelete() {
auto smartPtr1 = make_shared<Simple>();
shared_ptr<Simple> smartPtr2(smartPtr1);
}
// Simple constructor called!
// Simple destructor called!
3.1 weak_ptr
weak_ptr本身也是一个模板类,但是不能直接用它来定义一个智能指针的对象,只能配合shared_ptr来使用,可以将shared_ptr的对象赋值给weak_ptr,并且这样并不会改变引用计数的值。