对象生命周期(RAII)与智能指针所有权:

TEST(test_buffer, allocate) {
  using namespace base;
  auto alloc = base::CPUDeviceAllocatorFactory::get_instance();
  {
    Buffer buffer(32, alloc);
    ASSERT_NE(buffer.ptr(), nullptr);
    LOG(INFO) << "HERE1";
  }
  LOG(INFO) << "HERE2";
}

TEST(test_buffer, allocate2) {
  using namespace base;
  auto alloc = base::CPUDeviceAllocatorFactory::get_instance();
  std::shared_ptr<Buffer> buffer;
  { buffer = std::make_shared<Buffer>(32, alloc); }
  LOG(INFO) << "HERE";
  ASSERT_NE(buffer->ptr(), nullptr);
}

对于第一个测试:

用日志可以非常清楚地“卡点”析构时机:

这类写法非常适合验证 RAII:作用域结束资源必须释放。


而对于第二个测试:

make_shared<Buffer> 在 堆上创建 Buffer 对象。

本例中通常是测试函数结束时 buffer 离开作用域才析构(或你显式 buffer.reset())。

因此:

在 LOG(INFO) << "HERE"; 和 ASSERT_NE(buffer->ptr(), nullptr); 时,

这里有个点非常重要,buffer 这个共享指针在大括号开始之前就已经定义好了,但是在大括号内分配了一个堆对象使得 buffer 指向这个堆对象,所以大括号结束之后,buffer 还是会指向申请的堆对象的。

这里要说明一点,在 c++ 中只有有名字的对象才是变量,才有作用域。