对于拥有构造函数的对象而言 new ABC 与 new ABC() 效果等同,但对于内置类型而言,eg. new int 指向的int未初始化,而 new int()指向的int采用值初始化(0)
动态内存管理3个常见问题:
1.忘记 delete
2.使用以及释放的内存,释放内存后将其置为 nullptr 是个好习惯,防止野指针,但是保护有限,比如可能存在多个指针指向相同的内存
3.重复delete(p437)
坚持只使用智能指针可以避免所有这些问题! 智能指针和内置指针最好不要混用(因为一旦智能指针接管了内置指针,就可能在某些时候释放他)!
智能指针类能记录有多少个用户通过 shared_ptr 指向了相同的对象,并在无 shared_ptr 指向对象时,将对象释放
(机制很像 garbage collect,看起来是内置指针wrap了一层,大家都使用wrapped管理结构access内置指针指向的对象,
wrapped管理结构每个用户分配一个,拷贝或赋值的时候会先更新wrapped管理结构,然后分裂出一个新的wrapped管理结构传出去)
shared_ptr<double> p1; //将被初始化为空指针
shared_ptr<int> p2(new int(1024)); //p2指向一个值为1024的int(或者说,p2接管了内置指针),用来构造智能指针的内置指针必须指向动态内存,因为只能指针指不定什么时候就用delete将其释放啦
shared_ptr<int> p3 = new int(1024); //错误的! 因为c++没有提供内置指针到智能指针的隐式转换
caffe 中智能指针使用例子:
vector<shared_ptr<Layer<Dtype> > > layers_;
for (int layer_id = 0; layer_id < param.layer_size(); ++layer_id) {
layers_.push_back(LayerRegistry<Dtype>::CreateLayer(layer_param));
}
shared_ptr<SyncedMemory> diff_; //梯度信息
diff_.reset(new SyncedMemory(capacity_ * sizeof(Dtype))); //reset()可能会触发智能指针原来指向那块内存的释放操作
智能指针调用 get() 将返回其管理的内置指针,但是:
1.不准使用内置指针的代码使用delete将其释放(这是智能指针干的活)
2.不准用内置指针再去构造另一个智能指针(两个智能指针管理一个内置指针会混乱的!我怎么知道另一个智能指针是否已经将动态内存给释放了呢??)
智能指针可以确保即使异常发生(在释放资源的代码之前),资源也可以被正确释放(p441)
智能指针管理的类需要一个析构函数,且需要正确的在析构函数中释放资源,否则智能指针也帮不了你了
c++primer p438 表12.3很有用
c++primer p443 智能指针注意事项总结
https://www.cnblogs.com/diysoul/p/5930396.html
https://www.2cto.com/kf/201612/580580.html
https://www.cnblogs.com/lsgxeva/p/7788061.html
如果限制 shared_ptr 不可以进行普通的拷贝和赋值,那就是 unique_ptr ,unique_ptr 只允许某个用户独占,可以转移给其他用户但是不可以俩用户共享
weak_ptr 指向一个 shared_ptr 管理的对象,但是不会触发 shared_ptr 更改引用计数,即 一旦最后一个指向对象的 shared_ptr 被销毁,对象就被释放,即使还有 weak_ptr 指向这个对象
std::unique_ptr<int> up1(new int(11)); // 无法复制的unique_ptr
//unique_ptr<int> up2 = up1; // err, 不能通过编译
std::unique_ptr<int> up3 = std::move(up1); // 现在p3是数据的唯一的unique_ptr
//std::cout << *up1 << std::endl; // err, 运行时错误
up3.reset(); // 显式释放内存
up1.reset(); // 不会导致运行时错误
//std::cout << *up3 << std::endl; // err, 运行时错误
std::unique_ptr<int> up4(new int(22));
up4.reset(new int(44)); //"绑定"动态对象
std::cout << *up4 << std::endl; // 44
up4 = nullptr;//显式销毁所指对象,同时智能指针变为空指针。与up4.reset()等价
std::unique_ptr<int> up5(new int(55));
int *p = up5.release(); //只是释放控制权,不会释放内存
std::cout << *p << std::endl;
//cout << *up5 << endl; // err, 运行时错误
delete p; //释放堆区资源
void check(std::weak_ptr<int> &wp)
{
std::shared_ptr<int> sp = wp.lock(); // 转换为shared_ptr<int>
if (sp != nullptr)
{
std::cout << "still: " << *sp << std::endl;
}
else
{
std::cout << "still: " << "pointer is invalid" << std::endl;
}
}
std::shared_ptr<int> sp1(new int(22));
std::shared_ptr<int> sp2 = sp1;
std::weak_ptr<int> wp = sp1; // 指向shared_ptr<int>所指对象
std::cout << "count: " << wp.use_count() << std::endl; // count: 2
std::cout << *sp1 << std::endl; // 22
std::cout << *sp2 << std::endl; // 22
check(wp); // still: 22
sp1.reset();
std::cout << "count: " << wp.use_count() << std::endl; // count: 1
std::cout << *sp2 << std::endl; // 22
check(wp); // still: 22
sp2.reset();
std::cout << "count: " << wp.use_count() << std::endl; // count: 0
check(wp); // still: pointer is invalid