cpp-smartpointer

转移笔记

错误#4:没有使用make_shared来初始化shared_ptr!

相较于使用裸指针,make_share有两个独特的优点:

  1. 性能: 当你用new创建一个对象的同时创建一个shared_ptr时,这时会发生两次动态申请内存:一次是给使用new申请的对象本身的,而另一次则是由shared_ptr的构造函数引发的为资源管理对象分配的。
shared_ptr<aircraft> pAircraft(new Aircraft("F-16")); // Two Dynamic Memory allocations - SLOW !!!
</aircraft>

与此相反,当你使用make_shared的时候,C++编译器只会一次性分配一个足够大的内存,用来保存这个资源管理者和这个新建对象。

shared_ptr<aircraft> pAircraft = make_shared<aircraft>("F-16"); // Single allocation - FAST !
</aircraft></aircraft>
  1. 在看了MS编译器的memory头文件实现以后,我发现当内存分配失败时,这个对象就会被删除掉。这样的话使用裸指针初始化也不用担心安全问题了。
    建议- 使用make_shared而不是裸指针来初始化共享指针。

unique_ptr

std::unique_ptr
只有一个智能指针指向对象,不能共享。

  1. 无法进行复制构造与赋值操作.
  2. 可以进行移动构造和移动赋值操作
  3. 可做为容器元素
// 通过原始指针创建 unique_ptr 实例
std::unique_ptr<Task> taskPtr(new Task(23));

// 内部缓存
std::unique_ptr<unsigned char[]> m_spBuf;

// 方法2
if(m_spBuf == nullptr)
std::cout<<"m_spBuf is empty"<<std::endl;

m_pBufLength = 1024000;
m_spBuf = std::make_unique<unsigned char[]>(m_pBufLength);

m_pBufLength *= 10;
m_spBuf.reset(new unsigned char[m_pBufLength]);

m_spBuf.reset(nullptr);

unique_ptr<int> sp(new int(88) );
vector<unique_ptr<int> > vec;
vec.push_back(std::move(sp));
//vec.push_back( sp ); 这样不行,会报错的.
//cout<<*sp<<endl;执行了 move 操作之后 sp 被释放了


std::unique_ptr<dbo::backend::Postgres> m_pDb;
m_pDb = make_unique<dbo::backend::Postgres>(dbo::backend::Postgres(dbconn));

C++14 提供了 make_unique 来创建

auto ptr = make_unique<std::string>("senlin");
std::unique_ptr<char[]> chars(new char[1024]);

C++11 简单封装一下

template<typename T, typename... Ts>
std::unique_ptr<T> make_unique(Ts&&... params)
{
return std::unique_ptr<T>(new T(std::forward<Ts>(params)...));
}

shared_ptr

使用引用还是值传递参数?
简短的答案是:没有理由使用值传递

by const reference: void foo(const shared_ptr<T>& p)
or by value: void foo(shared_ptr<T> p)

std::make_shared<类型>(参数);

This question has been discussed and answered by Scott, Andrei and Herb during Ask Us Anything session at C++ and Beyond 2011. Watch from 4min 34sec on shared_ptr performance and correctness.

使用 std::move

void CompilerInstance::setInvocation(
std::shared_ptr<CompilerInvocation> Value) {
Invocation = std::move(Value);
}

std::shared_ptr 的引用计数是原子操作,比非原子操作耗时。
通过 move 操作,复制了原指针的引用计数,同时原指针置为空

std::make_shared

#include <iostream>
#include <memory>

void foo(const std::shared_ptr<int>& i)
{
(*i)++;
}

int main()
{
auto sp = std::make_shared<int>(12);
foo(sp);
std::cout << *sp << '\n';
}

weak_ptr