当前位置:首页 » 操作系统 » sharedptr源码

sharedptr源码

发布时间: 2022-10-05 11:58:22

① 不想编译boost库如何引用boost库的头文件啊

需定义相应的宏,如你不希望使用date_time库的动态链接库,你可以定义BOOST_DATE_TIME_SOURCE和BOOST_DATE_TIME_NO_LIB来使用切入源码的方式。不同库需要定义不同的宏

② vs2008关于C++的shared_ptr

shared_ptr需要VS2008 SP1以上才自带有,头文件为#include <memory>,或者使用boost库(boost::shared_ptr),头文件为#include <boost/shared_ptr.hpp>

vs2008 error C2039: “shared_ptr”: 不是“std::tr1”的成员

vs2008创建的c++项目中用到了std::tr1::shared_ptr,
编译时报错:error C2039: “shared_ptr”: 不是“std::tr1”的成员。
原因:未安装vs2008 SP1
VS90sp1-KB945140-CHS.exe:
http://www.microsoft.com/downloads/zh-cn/details.aspx?FamilyID=FBEE1648-7106-44A7-9649-6D9F6D58056E
VS2008SP1CHSX1512981.iso:
http://www.microsoft.com/downloads/zh-cn/details.aspx?FamilyID=27673C47-B3B5-4C67-BD99-84E525B5CE61
若 不安装vs2008 SP1,也可使用Boost的实现boost::shared_ptr

③ c++智能指针有哪些

在C++编程中,智能指针绝对是很强大的用法,boost库里把这些指针用的出神入化,它可以简化程序员写代码的复杂度,不用去考虑代码分支路径导致的遗漏delete语法,也无须担心冗余delete导致的double free问题。但是,便利性也要求程序猿熟悉各种指针的用法,避免误用,反而带来其他问题。下面简要列下常用的智能指针,及其用法:
1.scoped_ptr:这是最常用的智能指针,当你new一块内存后,把内存地址交给scoped_ptr管理,这样就不用显式调用delete了,当离开作用于后,该内存会被自动释放,如
int* p = new int;
scoped_ptr<int> scoped_int_ptr(p);
注意:无须再delete p;这样会double free。另外一个重要的点是:scoped_ptr不允许传递指针,即他的拷贝构造和赋值函数都是private的,不允许调用,所以你不能写如下代码
scoped_ptr<int> scoped_int_ptr2 = scoped_int_ptr; // 不允许
2.auto_ptr:它和scoped_ptr用法基本是一致的,但是它允许指针传递,拷贝构造和赋值函数允许调用,故名思意,当发生赋值时,原对象的指针会转移给新对象,这时原对象的指针就为NULL了,不能再调用。所以,对指针要把握好,使用应谨慎。
3.shared_ptr:scoped_ptr一样包装了new操作符在堆上分配的动态对象,但它实现的是引用计数型的智能指针 ,可以被自由地拷贝和赋值,在任意的地方共享它,当没有代码使用(引用计数为0)它时才删除被包装的动态分配的对象。但是,shared_ptr注意不要有循环引用,否则会出现内存泄漏。例如:A和B对象互相引用,它们的引用计数都是1,当出了作用域之后,二者不能自动释放,出现了内存泄漏。
4.weak_ptr:是一种智能指针,它对被 std::shared_ptr 管理的对象存在非拥有性(“弱”)引用。在访问所引用的对象前必须先转换为 std::shared_ptr。
std::weak_ptr 用来表达临时所有权的概念:当某个对象只有存在时才需要被访问,而且随时可能被他人删除时,可以使用std::weak_ptr 来跟踪该对象。需要获得临时所有权时,则将其转换为 std::shared_ptr,此时如果原来的std::shared_ptr 被销毁,则该对象的生命期将被延长至这个临时的 std::shared_ptr 同样被销毁为止。
此外,std::weak_ptr 还可以用来避免 std::shared_ptr 的循环引用。

④ c++关于shared_ptr的问题

shared_ptr<char> sc(new char[10]);
shared_ptr<char> sc(new char[10] {'a', 'b', 'c', 'd'});

⑤ C11新特性之智能指针

程序都是在堆上存储动态分配对象,而它的生存期是由程序来控制的。这就意味着当动态对象不再使用的时候,我们需要显式的将它销毁。

c98提出了一个智能指针auto_ptr为了避免人们使用指针时忘记释放内存。但是因为auto_ptr的总总缺点,使人们在开发过程碰到了各种坑,所以才有了c11新的三个智能指针。

移动语义是c11提出的,c11最大的特性就是拥有了移动而不是拷贝对象的能力,这就大幅度的提升了性能。
为了让自定义类型的对象也支持移动操作,我们为它定义了 移动构造函数 移动赋值运算符
移动构造函数是对资源进行窃取而不是拷贝。它的第一个参数是该类类型的右值引用,移动构造函数除了完成资源移动外,还必须保证移动之后的原对象处于 有效的、可析构 的状态(将原对象值赋值给新对象,然后把原对象属性值置空,特别是指针成员置空!那么此时原对象就是处于可析构的安全状态)。

看了memory里的部分源码,发现有一个在c11之前没有出现过的关键字explict

有了explict关键字的限定,防止类构造函数进行隐式转换

它禁止拷贝语义,但是是通过移动语义(什么是移动语义?上面有解答)来实现的。它“唯一”拥有它所指的对象。
从下面的unique_ptr的构造函数就可以发现它是禁止拷贝语义的。

但是如果想要切换指针的控制权,可以使用下面的移动构造函数来进行控制权的转化,这里用到forward转发(上一节可以知道forward转发可以返回该参数本来对应的类型的引用),其实这里就是把右值对象移动给左值,并且把右值对象置空

了解了前面的auto_ptr和unique_ptr,再来理解shared_ptr非常容易。
与前面两者不同的是,shared_ptr允许多个指针指向相同对象,前两者在切换控制权时,会将前面的清除,而shared_ptr不会。

当删除其中一个智能指针时,另外两个并不会受到变化。因为此时内存中存在着引用计数,每添加一个shared_ptr,引用计数+1,每次调用析构函数,引用计数-1。直到引用计数减为0,才会释放该块内存。
auto_ptr和unique_ptr都可以通过move函数转换成shared_ptr类型
当使用shared_ptr时,最需要注意的就是 避免循环引用 ,它会造成堆内存无法正常释放,出现内存泄露。如何解决这个问题呢,这时候就要用到weak_ptr的lock()锁

我们最好在使用weak_ptr访问对象时,使用lock()函数,它可以检测weak_ptr访问的对象是否存在,如果存在,返回一个内存中的shared_ptr对象,不存在,返回一个nullptr的shared_ptr

当双向链表的前驱指针和后继指针使用了shared_pre,如下

由于使用了shared_pre,一块内存空间有两个对象进行管理,而无法使引用计数为0,那么编译器就无法自动释放内存。

使用弱引用,弱引用并不会修改对象的引用计数,也就是弱引用并不会对对象的内存进行管理。但是它能检测到引用对象是否被释放,避免了内存泄露。weak_pre就是弱引用。

⑥ 请教C++语句:shared_ptr<T>static_pointer_cast(const shared_ptr<U>&r)

很简单,这是一个函数。
shared_ptr<T>是返回值
函数名称:static_pointer_cast;
参数const shared_ptr<U>&r'
就这么简单。

补充:那不叫取址。。那叫引用。
你难道这点c++基础都没有?那你还敢看Boost源码?

⑦ 如何把普通指针转为智能指针share

最近项目中使用boost库的智能指针,感觉智能指针还是蛮强大的,在此贴出自己学习过程中编写的测试代码,以供其他想了解boost智能指针的朋友参考,有讲得不正确之处欢迎指出讨论。当然,使用boost智能指针首先要编译boost库,具体方法可以网上查询,在此不再赘述。

智能指针能够使C++的开发简单化,主要是它能够自动管理内存的释放,而且能够做更多的事情,即使用智能指针,则可以再代码中new了之后不用delete,智能指针自己会帮助你管理内存资源的释放。

Boost库的智能指针有很多种,下面通过示例代码来说明其中share_ptr的使用方法。

// test.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include <iostream>
#include <boost/shared_ptr.hpp>
#include <vector>

/** 测试类 */
class CTest
{
public:

/** 构造函数 */
CTest(int m)
{
m_member = m;

/** 申请空间 */
m_pname = new char[2];
}
/** 析构函数 */
~CTest()
{
delete m_pname;
}

/** 成员函数 */
int getMember()
{
return m_member;
}

private:

/** 数据成员 */
int m_member;
char * m_pname;

};

int _tmain(int argc, _TCHAR* argv[])
{

/** 示例代码【1】 */

/** boost::shared_ptr智能指针含有一个引用计数器 */
/** 引用指针计数器记录有多少个引用指针指向同一个对象,如果最后一个引用指针被销毁的时候,那么就销毁对象本身。 */

/** 使用智能指针创建一个对象 */
/** 注意: 智能指针不支持直接 new 例如: boost::shared_ptr<CTest> pTemp = new CTest(2) 是错误的 */
boost::shared_ptr<CTest> pTemp(new CTest(10));

/** 创建一个新的智能指针也指向新创建的CTest对象 */
/** 智能指针支持等号操作 */
boost::shared_ptr<CTest> pSecond = pTemp;

/** 通过智能指针访问该对象 */
std::cout << pTemp->getMember() << std::endl;

/** 让第一个智能指针为空,不再指向该对象,注意,智能指针不能使用 pTemp = NULL */
pTemp.reset();

/** 让第二个智能指针也为空,这时该CTest对象已经没有智能指针指向它了,会自动析构 */
pSecond.reset();

/** 示例代码【2】 */

/** 将一个普通的指针转换为智能指针 */

/** 创建一个普通的指针,new一个对象 */
CTest * pATest = new CTest(100);
/** 转换为智能指针 */
boost::shared_ptr<CTest> pShareTest(pATest);

/** 智能指针会自动管理创建的CTest对象,不允许再进行delete,否则程序会挂掉 */
delete pATest;

/** 让智能指针为空,则对象会被自动析构 */
pShareTest.reset();

/** 示例代码【3】 */

/** 创建一个容器存放智能指针 */
/** 这里需要注意: 两个“ > ” 不要写到一起了,否则会产生 >> 运算符重载 */
std::vector<boost::shared_ptr<CTest> > vec;

/** 创建一个临时的CTest对象,存放到上面的容器 */

{

⑧ 如何:创建和使用shared_ptr实例

make_shared 是异常安全的。它使用同一调用分配的内存控制块和该资源从而减少构造开销。如果不使用 make_shared,则必须使用显式新的表达式创建对象,然后将其传递给 shared_ptr 构造函数之前。下面的示例演示各种方式与新的对象同时声明和初始化 shared_ptr。VBC#C++F#JScriptPowerShell No code example is currently available or this language may not be supported. 下面的示例演示如何声明和初始化采用对象共享所有权另一 shared_ptr已分配的 shared_ptr 实例。假定,sp2 是初始化的 shared_ptr。VBC#C++F#JScriptPowerShell No code example is currently available or this language may not be supported. shared_ptr 也很有用在标准模板库 (STL) 容器,当您使用"复制元素的算法时。可以包装在 shared_ptr的元素,然后将其复制到完全理解的其他容器基础内存有效,只要不需要且不再。下面的示例在矢量演示如何使用在 shared_ptr 实例的 replace__if 算法。VBC#C++F#JScriptPowerShell No code example is currently available or this language may not be supported. 可以使用 dynamic_pointer_cast、static_pointer_cast和const_pointer_cast 转换shared_ptr。这些功能类似于 dynamic_cast、static_cast和const_cast 运算符。下面的示例演示如何测试每个元素的派生类型在基类 shared_ptr 矢量的,然后复制元素并显示有关它们的信息。VBC#C++F#JScriptPowerShell No code example is currently available or this language may not be supported. 可以通过以下方式通过 shared_ptr 到另一个函数:通过shared_ptr 值。此调用复制构造函数,会递增引用计数,并使被调用方所有者。具有此操作的少量系统开销,可能是有意义的根据经历 shared_ptr 对象通过。使用此选项,当代码协定 (提示或显式) 时在调用方和被调用方之间要求被调用方是所有者。通过shared_ptr 引用或常数引用。在这种情况下,引用计数不增加,因此,被调用方可以访问指针,只要调用方不超出范围。或者,则被调用方可以决定创建基于引用的 shared_ptr 从而形成一个共享的所有者。使用此选项,当调用方不了解被调用方时,或者,如果必须通过 shared_ptr 和若要出于性能原因时避免复制操作。通过基础指针或引用为基础对象。这使得被调用方使用对象,但是,不使共享所有权或扩展生存期。如果被调用方创建原始指针的 shared_ptr,新 shared_ptr 与原来的是独立的和不控制此类基础资源。使用此选项,则在调用方和被调用方之间的协定的清单指定时调用方保留 shared_ptr 生存期的所有权。当您决定如何通过 shared_ptr,确定被调用方是否必须共享这种基础资源的所有权。“所有者”是可以使这种基础资源运行的对象或函数,只要它需要它。如果调用方必须确保则被调用方可以扩展指针的生存期在其 (函数) 的生存期以外的,请使用第一个选项。如果您不关心被调用方是否扩展生存期,则可以通过引用并允许被调用方复制它。如果必须允许帮助器到基础指针的函数访问,因此,您了解 helper 函数将使用指针和返回,在被调用函数返回以前,则该函数不必共享基础指针的所有权。它必须对调用方的 shared_ptr的生存期内指针。在这种情况下,通过 shared_ptr 引用或通过原始的指针或引用为基础对象是安全的。通过此方式提供一个小的性能改进,并且还有助于表示您编程的用途。

⑨ shared_ptr实现和线程安全分析

使用该智能指针(或者其他两种)需要导入头文件 #include <memory>

除此之外还可以对 shared_ptr 赋值,通过重写 operator= 实现。 需要注意 ,对于 p1=p2 (均为智能指针)这种, p2 所指对象由于被 p1 指向,所以该引用计数会加一, p1 原本指向的资源的引用计数会减一。这也会引出下面关于 shared_ptr 指针的 线程安全 问题。

运行结果如下:

这里实现的还有一些问题,因为 shared_ptr 源码中关于引用计数是 原子操作 ,不需要考虑资源使用冲突的问题,可以在自己实现的时候加锁。

首先什么是线程安全?
简单来说就是 多个线程操作一个共享数据,都能按照预期的行为进行,无论多个线程的运行次序如何交织。

对于 shared_ptr ,其内部有两个变量,引用计数和真正的对象类型指针。其中引用计数是原子操作,所以 对于 shared_ptr 的读操作是线程安全的。

但是对于 shared_ptr 中赋值如 ptr1 = ptr2 ,需要两个步骤, 1、 ptr1 的内部对象指针 Obj1 替换成 ptr2 内部对象 Obj2 指针;2、 ptr1 的对于 Obj1 的引用计数缓存 Obj2 的引用计数。

这两步并不是原子的,如果一个线程需要对 shared_ptr 进行赋值操作 ptr1 = ptr2 ,刚完成第一步,就切换到其他线程又对ptr2进行操作,如 ptr2 = ptr3 ,就有可能造成析构了引用计数。而继续之前线程的第二步,就会出错。

总之:对于 shared_ptr 的读操作是线程安全的。
对于 shared_ptr 读写操作不是线程安全的,需要加锁。

tips:为什么 shared_ptr 的引用计数能够同步到不同的指针中?

有人回答可能使用的是static变量,这是不可能的,因为一个类中只有一个静态变量,只能记录对于一个对象的引用次数,这在包含两个 shared_ptr 以上的程序中是不可行的。
个人认为是引用计数是用指针实现的,指向一个记录引用次数的对象。

热点内容
个密码算法 发布:2024-05-08 13:18:27 浏览:383
编程四要素 发布:2024-05-08 13:13:21 浏览:299
手机扣扣如何设置密码 发布:2024-05-08 13:04:35 浏览:237
sql注入攻击与防御 发布:2024-05-08 12:58:38 浏览:317
dw网页设计如何连接服务器 发布:2024-05-08 12:33:02 浏览:465
linux文件隐藏命令 发布:2024-05-08 12:29:38 浏览:748
信息增益python 发布:2024-05-08 12:23:49 浏览:549
外置内存卡不能存储 发布:2024-05-08 11:43:02 浏览:507
javalist合并 发布:2024-05-08 11:43:01 浏览:477
校园网内怎么搭建服务器 发布:2024-05-08 11:28:33 浏览:73