必须包含头文件#include <memory>
std::auto_ptr 在C++11中被废弃 采用所有权模型
std::auto_ptr<Class> className;
采用所有权模型,当值被其他auto_ptr赋值时,所有权交予他人,本指针变为空地址
例如:
std::auto_ptr<Class> className1(new Class()));
std::auto_ptr<Class> className2(className1);
此时所有权交给className2, className1指针变为空指针
如下图所示,打印指针为空
std::unique_ptr 采用所有权模型 唯一指针
std::unique_ptr<Class> className;
例如:
std::unique_ptr<Class> className1(new Class()));
std::unique_ptr<Class> className2(className1);
此时是非法的,会报编译错误unique_ptr比auto_ptr的策略更严格,不容易出错
如下图所示
使用移std::move(),能够将指针赋值给另外一个智能指针,当前智能指针变为空
std::unique_ptr可以充当函数的参数,以及返回值当参数
void Test(std::unique_ptr<std::string> str)
{
std::cout << *str << std::endl;
}
int main()
{
std::unique_ptr<std::string> str(new std::string("this is a test..."));
Test(std::move(str));
return 0;
}
当返回值,return语句不需要move的原因是根据C++11的语言规则编译器将自动尝试移动
std::unique_ptr<std::string> Test()
{
std::unique_ptr<std::string> str(new std::string("this is a test..."));
return str;
}
int main()
{
std::unique_ptr<std::string> str = Test();
std::cout << *str << std::endl;
return 0;
}
std::unique_ptr 造成段错误
如下所示,此时新建两个唯一指针,同时指向int,当析构时就会造成二次析构,这就会造成析构两次,double free错误
class Test
{
public:
~Test()
{
qDebug() << "Destory Test";
}
};
int main()
{
Test *test = new Test();
std::unique_ptr<Test> pTest1(test);
std::unique_ptr<Test> pTest2(test);
return 0;
}
std::shared_ptr 采用引用计数模型 智能更高的指针 共享指针
std::shared_ptr<Class> className;
每增加一个引用操作,shared_ptr内部计数会增加1
例如:
std::shared_ptr<Class> className1(new Class()));
std::shared_ptr<Class> className2(className1);
此时是引用计数为2,当引用计数,当指针过期时,引用计数减1,仅当最后一个指针过期时,才会调用delete释放资源,共享指针不是线程安全的
如下图所示
std::shared_ptr 创建的三种方式
std::shared_ptr<std::string> pTest{new std::string("Test")};
std::shared_ptr<std::string> pTest(new std::string("Test"));
std::shared_ptr<std::string> pTest = std::make_shared<std::string>("Test");
推荐:使用第三种方式进行创建,更快(一次复制),更安全
std::shared_ptr 放入容器中
如下所示,此时的引用计数为2,在创建时引用计数为1,在加载进容器时,引用计数为2,向容器中插入共享指针,只是其引用计数会增加,两个指针同时指向一个对象
std::vector<std::shared_ptr<std::string>> testVector;
std::shared_ptr<std::string> pTest = std::make_shared<std::string>("Test");
testVector.push_back(pTest);
std::shared_ptr 造成段错误
如下所示,此时新建两个共享指针,同时指向Test,但此时的pTest1和pTest2的引用计数都为1,这就会造成析构两次,double free错误
class Test
{
public:
~Test()
{
qDebug() << "Destory Test";
}
};
int main()
{
Test *pTest = new Test();
std::shared_ptr<Test> pTest1(pTest);
std::shared_ptr<Test> pTest2(pTest);
std::cout << "Use Count pTest1:"<< pTest1.use_count() << std::endl;
std::cout << "Use Count pTest2:"<< pTest2.use_count() << std::endl;
return 0;
}
std::shared_ptr使用std::enable_shared_from_this和shared_from_this()
std::enable_shared_from_this 能让一个对象(假设其名为 t ,且已被一个 std::shared_ptr 对象 pt 管理)安全地生成其他额外的 std::shared_ptr 实例(假设名为 pt1, pt2, ... ) ,它们与 pt 共享对象 t 的所有权。
若一个类 T 继承 std::enable_shared_from_this<T> ,则会为该类 T 提供成员函数: shared_from_this 。 当 T 类型对象 t 被一个为名为 pt 的 std::shared_ptr<T> 类对象管理时,调用 T::shared_from_this 成员函数,将会返回一个新的 std::shared_ptr<T> 对象,它与 pt 共享 t 的所有权。
class Test : public std::enable_shared_from_this<Test>
{
public:
~Test()
{
qDebug() << "Destory Test";
}
std::shared_ptr<Test> getSharedPtr()
{
return shared_from_this();
}
};
int main()
{
Test *pTest = new Test();
std::shared_ptr<Test> pTest1(pTest);
std::shared_ptr<Test> pTest2(pTest->getSharedPtr());
std::cout << "Use Count pTest1:"<< pTest1.use_count() << std::endl;
std::cout << "Use Count pTest2:"<< pTest2.use_count() << std::endl;
return 0;
}
此时不会造成段错误的情况,只释放了一次,且引用计数为2
强制类型转换
如下所示,将int型指针初始化为void型指针,在后面使用时使用static_pointer_cast强制转换回来
std::shared_ptr<void> pTest = std::make_shared<int>(100);
std::cout << *std::static_pointer_cast<int>(pTest);
std::static_pointer_cast
std::dynamic_pointer_cast
std::const_pointer_cast
std::reinterpret_pointer_cast()
对于智能指针的强制类型转换,智能使用上面四种进行强制类型转换,而不可使用C风格的static_cast<new_type> (expression) :
dynamic_cast<new_type> (expression) :
const_cast<new_type> (expression) :
reinterpret_cast <new_type> (expression) :
这四种强制类型转换
智能指针的销毁
定义删除器,对智能指针进行删除,如下所示使用Lambda表达式,销毁智能指针
class Test
{
public:
~Test()
{
qDebug() << "Destory Test";
}
};
int main()
{
std::shared_ptr<Test> pTest1(new Test(), [](Test *test)
{
std::cout << "Lambda delete" << std::endl;
delete test;
});
return 0;
}
或者
void delFunction(Test *test)
{
std::cout << "Lambda delete" << std::endl;
delete test;
}
int main()
{
std::shared_ptr<Test> pTest1(new Test(), delFunction);
return 0;
}
再或者
int main()
{
std::shared_ptr<Test> pTest1(new Test(), std::default_delete<Test>());
return 0;
}
前两种是一样的,第三种使用std::default_delete对智能指针进行删除