您的位置:首页 > 娱乐 > 八卦 > 企业宣传片制作软件_豆瓣网页版_百度快照优化排名_百度提交网址入口

企业宣传片制作软件_豆瓣网页版_百度快照优化排名_百度提交网址入口

2025/4/13 7:30:46 来源:https://blog.csdn.net/Coffeemaker88/article/details/144180643  浏览:    关键词:企业宣传片制作软件_豆瓣网页版_百度快照优化排名_百度提交网址入口
企业宣传片制作软件_豆瓣网页版_百度快照优化排名_百度提交网址入口

12.1.5 unique_ptr

一个 unique_ptr “拥有”它所指向的对象。

与 shared_ptr 不同,某个时刻只能有一个 unique_ptr 指向一个给定对象。(相当于 unique_ptr 会“独占”其所指向的对象,引用计数固定为 1)

当 unique_ptr 被销毁时,其所指向的对象也被销毁。

下表列出了 unique_ptr 的常用操作:
在这里插入图片描述
与 shared_ptr 不同,没有类似 make_shared 的标准库函数返回一个 unique_ptr。当我们定义一个 unique_ptr 时,需要将其绑定到一个 new 返回的指针上。类似 shared_ptr,初始化 unique_ptr 必须采用直接初始化形式:

unique_ptr<double> p1;		// 可以指向一个 double 的 unique_ptr
unique_ptr<int> p2(new int(42)); // p2 指向一个值为 42 的 int, 采用直接初始化的方式来完成

由于一个 unique_ptr 拥有它所指向的对象,因此 unique_ptr 不支持普通的拷贝或赋值操作:

unique_ptr<string> p1(new string("Stegosaurus"));
unique_ptr<string> p2(p1);	// 错误❌: unique_ptr 不支持拷贝
unique_ptr<string> p3;
p3 = p2;					// 错误❌: unique_ptr 不支持赋值

虽然不能拷贝或赋值 unique_ptr,但是可以通过 release 或 reset 将指针的所有权从一个(非 const)的 unique_ptr 转移给另一个 unique_ptr:

unique_ptr<string> p2(p1.release());	// release 将 p1 释放为空, 返回内置指针
// 👆 所有权将从 p1 转移给 p2
unique_ptr<string> p3(new string("Trex"));
p2.reset(p3.release());					// reset 释放了 p2 原先指向的内存
// 👆 p2 释放内存之后, 接受其参数, 它是由 p3 释放的内置指针, 因此 p3 将所有权转交给 p2

reset 成员接受一个可选的指针参数,它令 unique_ptr 重新指向给定的指针。

调用 release 会切断 unique_ptr 和它原来管理的对象之间的联系。

传递 unique_ptr 参数和返回 unique_ptr

不能拷贝 unique_ptr 的规则有一个例外:可以拷贝或赋值一个将要被销毁的 unique_ptr。最常见的例子就是返回一个 unique_ptr:

unique_ptr<int> clone(int p) {return unique_ptr<int>(new int(p));
}

还可以返回一个局部对象的拷贝:

unique_ptr<int> clone(int p) {unique_ptr<int> ret(new int(p));// ...return ret;
}

向 unique_ptr 传递删除器

类似 shared_ptr,unique_ptr 默认情况下使用 delete 释放它所指向的对象。与 shared_ptr 一样,可以重载一个 unique_ptr 中默认的删除器。但是,unique_ptr 管理删除器的方式与 shared_ptr 不同。

重载一个 unique_ptr 中的删除器会影响到 unique_ptr 类型以及如何构造该类型的对象。必须在尖括号 unique_ptr 指向类型之后提供删除器类型。在创建或 reset 一个这种 unique_ptr 类型的对象时**,必须提供一个指定类型的可调用对象(删除器)**:

unique_ptr<objT, delT> p(new objT, fcn);

以下是一个更具体的例子,在该例当中,使用 unique_ptr 代替 shared_ptr:

void f(destination &d) {connection c = connect(&d);unique_ptr<connection, decltype(end_conenction)*> p(&c, end_connection);
}

12.1.6 weak_ptr

weak_ptr 是一种不控制所指向对象生存期的智能指针(shared_ptr 在内存地址引用计数为 0 时自动将动态内存进行回收,而 unique_ptr 独占动态内存,当 unique_ptr 被销毁时,与其一一对应的动态内存也被回收),它指向一个 shared_ptr 管理的对象。

将一个 weak_ptr 绑定到一个 shared_ptr 不会改变 shared_ptr 的引用计数。一旦最后一个指向对象的 shared_ptr 被销毁,对象就会被释放。即使有 weak_ptr 指向对象,对象也还是会被释放。

下表列出了 weak_ptr 的常用方法:在这里插入图片描述
当我们创建一个 weak_ptr 时,要用一个 shared_ptr 来初始化它:

auto p = make_shared<int>(42);
weak_ptr<int> wp(p);			// 使用 shared_ptr 来对 wp 进行初始化
// 👆 由于 wp 弱共享 p, p 的引用计数未变化

上例中 wp 和 p 指向相同的对象。由于是弱共享,创建 wp 不会改变 p 的引用计数;wp 指向的对象也可能会被释放掉。

由于对象不存在,不能使用 weak_ptr 直接访问对象,而必须调用 lock。lock 检查 weak_ptr 指向的对象是否仍然存在。如果存在,lock 返回一个指向共享对象的 shared_ptr(注意,lock 函数返回的是指向与 weak_ptr 共享对象的 shared_ptr)。与任何其它 shared_ptr 类似,只要此 shared_ptr 存在,它所指向的底层对象就会一直存在。例如:

if(shared_ptr<int> np = wp.lock()) {	// np 不为空则条件成立// 在 if 中, np 与 p 共享对象// np 的作用域仅限于这个方块内
}

核查指针类

为了展示 weak_ptr 的用途,下例为 StrBlob 定义一个伴随指针类。将这个指针命名为 StrBlobPtr,它会保存一个 weak_ptr,指向 StrBlob 的 data 成员,这是初始化时提供给它的。

通过使用 weak_ptr,不会影响一个给定的 StrBlob 所指的 vector 的生存期。但可以阻止用户访问一个不再存在的 vector 的企图。

StrBlobPtr 有两个数据成员:wptr,或者为空或者指向一个 StrBlob 中的 vector;curr,保存当前对象所表示的元素的下标。类似它的伴随类 StrBlob,我们的指针类也有一个 check 成员来检查解引用 StrBlobPtr 是否安全:

class StrBlobPtr {public:StrBlobPtr(): curr(0) {}StrBlobPtr(StrBlob &a, size_t sz = 0): wptr(a.data), curr(sz) { }std::string& deref() const;StrBlobPtr& incr();          // 前缀递增private:std::shared_ptr<std::vector<std::string>> check(std::size_t, const std::string&) const;std::weak_ptr<std::vector<std::string>> wptr;std::size_t curr;
};

默认构造函数生成一个空的 StrBlobPtr。其构造函数初始化列表将 curr 显式初始化为 0,并将 wptr 隐式初始化为一个空的 weak_ptr。

第二个构造函数接受一个 StrBlob 的引用,和一个可选的索引值。此构造函数初始化 wptr,令其指向给定 StrBlob 对象的 shared_ptr 中的 vector,并将 curr 初始化为 sz。

值得注意的是,不能将 StrBlobPtr 绑定到一个非 const StrBlob 对象。这个限制是由于构造函数接受一个非 const StrBlob 对象的引用导致的。

StrBlobPtr 的 check 成员与 StrBlob 中的同名成员不同,它还要检查指针指向的 vector 是否存在:

std::shared_ptr<std::vector<std::string>> StrBlobPtr::check(std::size_t i, const std::string &msg) const {auto ret = wptr.lock();     // 检查 vector 是否还存在if(!ret) {throw std::runtime_error("unbound StrBlobPtr");}if(i >= ret -> size()) {throw std::out_of_range(msg);}return ret;                 // 否则, 返回指向 vector 的 shared_ptr
}

指针操作

定义名为 deref 和 incr 的函数,分别用来解引用和递增 StrBlobPtr。

deref 成员调用 check,检查使用 vector 是否安全,以及 curr 是否在合法范围内:

std::string& StrBlobPtr::deref() const {auto p = check(curr, "dereference past end");return (*p)[curr];  // (*p)是对象所指向的 vector
}

incr 成员也调用 check:

// 👇 前缀递增, 返回递增后的对象的引用
StrBlobPtr& StrBlobPtr::incr() {// 👇 如果 curr 已经指向容器的尾部位置, 则不能再递增check(curr, "increment past end of StrBlobPtr");++ curr;     // 推进当前位置return *this;
}

为了能够访问 data 成员,必须在 StrBlob 的定义当中将 StrBlobPtr 声明为 friend。我们还要为 StrBlob 类定义 begin 和 end,返回一个指向它自身的 StrBlob:

class StrBlob {public:friend class StrBlobPtr;StrBlobPtr begin() { return StrBlobPtr(*this); }StrBlobPtr end() { auto ret = StrBlobPtr(*this, data -> size());return ret; }// 其它成员与 12.1.1 中的声明相同

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com