20200220

@ShiKaiWi

Plan

60min: CPP smart pointer

Notes

  • shared_ptr 和 unique_ptr 都无法进行赋值,weak_ptr 需要从 shared_ptr 构建。
  • shared_ptr 可以指定 deleter,尤其 share_ptr 从一个栈指针构建出来的时候,必须指定 deleter,否则就会对栈指针做 delete 操作,而这个是非法的。
  • allocator 可以做 allocate/deallocte、construct/destory 这两对操作,事实证明,delete ptr 是两步操作,调用 ptr 指向的类对象的析构函数,然后(destroy),然后回收相应的内存(deallocate)。
  • unique_ptr 类似 rust 里面的最普通的 Box 指针,只有一个 owner。

练习:

#include <iostream>
#include <memory>
#include <vector>

struct Obj {
  int i_;
  Obj(int i) : i_(i) {}
  ~Obj() { std::cout << "obj is freed, i=" << i_ << std::endl; }
};

void test_auto_new() {
  Obj obj(1);
  auto s = new auto(obj);
  delete s;
}

void test_delete_share_ptr_get() {
  auto sp = std::make_shared<int>();
  auto p = sp.get();
  // p can not be deleted otherwise double free will occur
  // delete p;
}

void test_delete() {
  Obj obj(3);
  // next line will cause &obj is deleted but the pointer
  // is never allocated before.
  // std::shared_ptr<Obj> p(&obj);

  std::shared_ptr<Obj> p(
      &obj, [](Obj *obj) { std::cout << "obj is custom freed" << std::endl; });
}

void test_unique_init() { std::unique_ptr<Obj> u(new Obj(4)); }

void test_alloc() {
  std::allocator<int> alloc;
  std::vector<int> vi = {1, 2, 3};
  auto p = alloc.allocate(vi.size() * 2);
  auto q = std::uninitialized_copy(vi.begin(), vi.end(), p);
  std::uninitialized_fill_n(q, vi.size(), 10);
  for (auto it = p; it != (p + vi.size() * 2); it++) {
    std::cout << *it << ", ";
  }
  std::cout << std::endl;
}

void test_alloc_destroy() {
  std::allocator<Obj> alloc;
  auto p = alloc.allocate(2);
  alloc.construct(p, 5);
  alloc.destroy(p);
  p->i_ = 6;
  alloc.destroy(p);
  alloc.deallocate(p, 2);
}

int main() {
  test_auto_new();
  test_delete_share_ptr_get();
  test_delete();
  test_unique_init();
  test_alloc();
  test_alloc_destroy();
  return 1;
}

More

  • std::initializer_list