这是一个基本问题,但我没有找到关于它的先前帖子.以下问题的标题听起来可能与我的问题相同,但问题本身与标题不匹配:使用shared_ptr.reset还是operator =?
我对reset()成员函数的目的感到困惑std::shared_ptr:除了赋值运算符之外,它还有什么作用呢?
具体来说,给定定义:
auto p = std::make_shared<int>(1);
Run Code Online (Sandbox Code Playgroud)
以下两行是否相同:
p = std::make_shared<int>(5);
p.reset(new int(5));
Run Code Online (Sandbox Code Playgroud)这些怎么样:
p = nullptr;
p.reset();
Run Code Online (Sandbox Code Playgroud)如果两条线在两种情况下都相同,那么目的是reset()什么?
编辑:让我重新说一下这个问题,以便更好地强调它的观点.问题是:是否有一种情况reset()可以让我们在没有它的情况下实现一些不容易实现的事情?
boost :: shared_ptr可以释放存储的指针而不删除它吗?
我可以看到文档中没有发布功能,也在FAQ中解释了为什么它不提供发布功能,类似于发布不能在不唯一的指针上完成.我的指针是独一无二的.我该如何发布我的指针?或者哪个提升智能指针类使用,这将允许我释放指针?我希望你不要说使用auto_ptr :)
从C++ 11开始,由于几个原因,开发人员倾向于将智能指针类用于动态生命周期对象.而对于那些新的智能指针类,标准,甚至建议不使用运营商,new而是建议使用make_shared或make_unique避免一些容易出错.
如果我们喜欢使用智能指针类shared_ptr,我们可以构建一个类似的,
shared_ptr<int> p(new int(12));
Run Code Online (Sandbox Code Playgroud)
我们还希望将自定义删除器传递给智能指针类,
shared_ptr<int> p(new int(12), deleter);
Run Code Online (Sandbox Code Playgroud)
另一方面,如果我们喜欢使用make_shared分配,例如.int,而不是使用new和shared_ptr构造函数,就像上面的第一个表达式,我们可以使用
auto ip = make_shared<int>(12);
Run Code Online (Sandbox Code Playgroud)
但是,如果我们也希望将自定义删除器传递给make_shared,那么有没有正确的方法呢?好像编译器,至少gcc,给出错误,
auto ip = make_shared<int>(12, deleter);
Run Code Online (Sandbox Code Playgroud) 我正在尝试研究如何将std :: shared_ptr与自定义删除器一起使用.具体来说,我将它与SDL_Surface一起用作:
std::shared_ptr<SDL_Surface>(SDL_LoadBMP(....),SDL_FreeSurface);
Run Code Online (Sandbox Code Playgroud)
编译并运行良好.但是,我想尝试自己的删除器,但无法解决如何操作.SDL_FreeSurface的文档可在此处找到:
http://sdl.beuc.net/sdl.wiki/SDL_FreeSurface
我在其中发现SDL_FreeSurface被声明为:
void SDL_FreeSurface(SDL_Surface* surface);
Run Code Online (Sandbox Code Playgroud)
作为测试,并通过该信息,我尝试了以下功能:
void DeleteSurface(SDL_Surface* surface)
{
std::cout << "Deleting surface\n";
SDL_FreeSurface(surface);
}
Run Code Online (Sandbox Code Playgroud)
但是,使用g ++编译会出现以下错误:
error: no matching function for call to 'std::shared_ptr<SDL_Surface>::shared_ptr(SDL_Surface*, <unresolved overloaded function type>)'
Run Code Online (Sandbox Code Playgroud)
我已经查看了gcc std :: shared_ptr实现的gnu文档,但是对它没有多大意义.我究竟做错了什么?
编辑:我已经缩小了问题的范围,但是会留下上面的原始问题.我所拥有的是一个Game类,如果我将其删除为基本实现,则类似于:
class Game {
public:
/* various functions */
private:
void DeleteSurface(SDL_Surface* surface);
bool CacheImages();
std::vector<std::shared_ptr<SDL_Surface> > mCachedImages;
/* various member variables and other functions */
}
Run Code Online (Sandbox Code Playgroud)
与上述执行DeleteSurface一样,执行CacheImages()如下:
bool CacheImages()
{
mCachedImages.push_back(std::shared_ptr<SDL_Surface>(SDL_LoadBMP(...),DeleteSurface);
return true;
}
Run Code Online (Sandbox Code Playgroud)
哪个游戏我上面列出的错误.但是,如果我将该DeleteSurface() …
这里引用了cppreference的实现说明部分std::shared_ptr,其中提到有两个不同的指针(如粗体所示):可以返回的指针get(),以及控制块中保存实际数据的指针.
在典型的实现中,
std::shared_ptr只保留两个指针:
- 存储的指针(返回一个
get())- 指向控制块的指针
控制块是一个动态分配的对象,它包含:
- 指向托管对象的指针或托管对象本身
- 删除(类型擦除)
- 分配器(类型擦除)
- 数量
shared_ptrs是自己的管理对象- 的数目
weak_ptrs引用该管理对象
shared_ptr直接保持的指针是由返回get()的指针,而控制块保持的指针或对象是当共享所有者的数量达到零时将被删除的指针或对象.这些指针不一定相等.
我的问题是,为什么托管对象需要两个不同的指针(两个粗体)(除了指向控制块的指针)?那个回来的人get()不够吗?为什么这些指针不一定相等?
在C++ 11中std::shared_ptr有四个构造函数,可以传递d类型的删除对象D.这些构造函数的签名如下:
template<class Y, class D> shared_ptr(Y * p, D d);
template<class Y, class D, class A> shared_ptr(Y * p, D d, A a);
template <class D> shared_ptr(nullptr_t p, D d);
template <class D, class A> shared_ptr(nullptr_t p, D d, A a);
Run Code Online (Sandbox Code Playgroud)
[util.smartptr.shared.const]类型中的标准要求D为CopyConstructible.为什么需要这个?如果shared_ptr制作d那些删除者中的哪一个可能被调用的副本?是不是shared_ptr只能保留一个删除器?如果可以复制shared_ptr,拥有删除器意味着什么d?
CopyConstructible要求背后的理由是什么?
PS:这个要求可能会使写作删除者复杂化shared_ptr.unique_ptr似乎对其删除有更好的要求.
scoped_ptr不能复制,并且正在删除范围之外.所以它有点受限制shared_ptr.因此,除了您真正需要限制复制操作的情况之外,shared_ptr最好使用.因为有时您不知道需要创建对象的副本或不需要.所以问题是:除了上面提到的情况之外,我们shared_ptr是否可以考虑使用更好(或推荐)代替scoped_ptr.是否scoped_ptr更快地工作shared_ptr,或者它有什么优势?
谢谢!
我不确定初始化shared_ptr一个类的成员的好方法.你能告诉我,我选择的方式是否C::foo()合适,还是有更好的解决方案?
class A
{
public:
A();
};
class B
{
public:
B(A* pa);
};
class C
{
boost::shared_ptr<A> mA;
boost::shared_ptr<B> mB;
void foo();
};
void C::foo()
{
A* pa = new A;
mA = boost::shared_ptr<A>(pa);
B* pB = new B(pa);
mB = boost::shared_ptr<B>(pb);
}
Run Code Online (Sandbox Code Playgroud) 我在想,如果我需要检查是否sp是null之前我用它.纠正我,如果我错了,但创建一个别名不会增加ref计数器,因此通过进入方法我们正在使用共享指针,我们不知道嵌入式指针是否已被重置..我是正确的假设这个?
Class::MyFunction(std::shared_ptr<foo> &sp)
{
...
sp->do_something();
...
}
Run Code Online (Sandbox Code Playgroud)