据我了解,在当前的C++ 11规范中,应该使用:
std::unique_ptr<> 对于一个所有者(大多数时间)std::shared_ptr<> 只有在非循环结构中有多个所有者时std::weak_ptr<> 只有在有需要打破的循环时才会谨慎所以我的问题是:
scoped_ptr<>和auto_ptr<>有效地过时了?我有一个现有的变量,例如
int a = 3;
Run Code Online (Sandbox Code Playgroud)
我现在如何才能创建一个boost::shared_ptr到a?例如:
boost::shared_ptr< int > a_ptr = &a; // this doesn't work
Run Code Online (Sandbox Code Playgroud) 换句话说,实现如何跟踪计数?
是否存在一个类似于地图的对象,所有shared_ptr实例都可以访问它们,其键是指针的地址,值是引用的数量?如果我要实现一个shared_ptr,这是我想到的第一个想法.
在这些引用计数智能指针的情况下是否存在内存泄漏的可能性?如果是这样,我该如何避免它们?
c++ memory-leaks memory-management smart-pointers shared-ptr
我经常需要在C++中处理动态分配的数组,因此依赖于Boost for scoped_array,shared_array等.在阅读了Stroustrup的C++ 11 FAQ和C++ 11 Reference Wiki之后,我无法找到C++ 11标准提供的这些动态数组包装器的合适替代品.有什么东西我忽略了,还是我必须继续依赖Boost?
非常感谢您的帮助!
通常,C++中引用计数智能ptr类的最广为人知的实现,包括标准std::shared_ptr,使用原子引用计数,但不提供对同一智能ptr实例的原子访问.换句话说,多个线程可以安全地在shared_ptr指向同一共享对象的单独实例上操作,但是多个线程不能安全地读取/写入同一shared_ptr实例的实例而不提供某种同步,例如互斥或其他.
已经提出了shared_ptr被称为" atomic_shared_ptr" 的原子版本,并且已经存在初步实现.据推测,可以使用自旋锁或互斥锁轻松实现,但也可以实现无锁实现.atomic_shared_ptr
在研究了其中一些实现后,有一件事是显而易见的:实现无锁std::shared_ptr是非常困难的,并且似乎需要这么多compare_and_exchange操作才能让我质疑简单的自旋锁是否会实现更好的性能.
实现无锁引用计数指针如此困难的主要原因是因为在读取共享控制块(或共享对象本身,如果我们讨论的是侵入式共享指针)之间总是存在竞争,并修改引用计数.
换句话说,您甚至无法安全地读取引用计数,因为您永远不知道其他某个线程何时释放了引用计数所在的内存.
因此,通常,采用各种复杂策略来创建无锁版本.这里的实现看起来像是使用双引用计数策略,其中有"本地"引用计算并发访问shared_ptr实例的线程数,然后是"共享"或"全局"引用,它们计算指向shared_ptr实例的数量到共享对象.
考虑到所有这些复杂性,我真的很惊讶地找到了Dobbs博士的文章,从2004年开始,(在C++ 11原子之前的方式)似乎无情地解决了整个问题:
http://www.drdobbs.com/atomic-reference-counting-pointers/184401888
看起来作者声称能够以某种方式:
"... [读取]指向计数器的指针,递增计数器,并以这样的方式返回指针 - 所有其他线程都不会导致错误的结果"
但我真的不明白他实际实现这一点的方式.他正在使用(非便携式)PowerPC指令(LL/SC原语lwarx和stwcx)将其关闭.
执行此操作的相关代码是他所谓的aIandF"(原子增量和提取)",他将其定义为:
addr aIandF(addr r1){
addr tmp;int c;
do{
do{
tmp = *r1;
if(!tmp)break;
c = lwarx(tmp);
}while(tmp != *r1);
}while(tmp && !stwcx(tmp,c+1));
return tmp;
};
Run Code Online (Sandbox Code Playgroud)
显然,addr …
我有一个继承自的类型enable_shared_from_this<type>,以及从这种类型继承的另一种类型.现在我不能使用shared_from_this方法,因为它返回基类型,并且在特定的派生类方法中我需要派生类型.从这个直接构造shared_ptr是否有效?
编辑:在一个相关的问题中,我如何从一个类型的左值移动shared_ptr<base>到一个类型shared_ptr<derived>?我使用dynamic_cast来验证它确实是正确的类型,但现在我似乎无法完成实际的移动.
我reset()用作shared_pointer的默认值(相当于a NULL).
但是如何检查shared_pointer是否是NULL?
这会返回正确的价值吗?
boost::shared_ptr<Blah> blah;
blah.reset()
if (blah == NULL)
{
//Does this check if the object was reset() ?
}
Run Code Online (Sandbox Code Playgroud) 先来看看什么C++入门谈到unique_ptr和shared_ptr:
$ 16.1.6.效率和灵活性
我们可以确定
shared_ptr不将删除器作为直接成员,因为删除器的类型直到运行时才知道.因为删除器的类型是a
unique_ptr类型的一部分,所以删除器成员的类型在编译时是已知的.删除器可以直接存储在每个unique_ptr对象中.
所以似乎shared_ptr没有直接的删除成员,但unique_ptr确实如此.然而,另一个问题的最高投票回答说:
如果将deleter作为模板参数提供(如
unique_ptr),则它是类型的一部分,您不需要在此类型的对象中存储任何其他内容.如果将deleteter作为构造函数的参数传递(如shared_ptr),则需要将其存储在对象中.这是额外灵活性的代价,因为您可以为相同类型的对象使用不同的删除器.
引用的两段完全相互矛盾,让我感到困惑.更重要的是,许多人说unique_ptr是零开销,因为它不需要将删除器存储为成员.但是,正如我们所知,unique_ptr有一个构造函数unique_ptr<obj,del> p(new obj,fcn),这意味着我们可以将删除函数传递给它,因此unique_ptr似乎已将删除函数存储为成员.真是一团糟!
boost::shared_ptr 有一个不寻常的构造函数
template<class Y> shared_ptr(shared_ptr<Y> const & r, T * p);
Run Code Online (Sandbox Code Playgroud)
我对这对什么有用感到有些疑惑.基本上它与股份共享r,但.get()将返回p.不 r.get()!
这意味着您可以执行以下操作:
int main() {
boost::shared_ptr<int> x(new int);
boost::shared_ptr<int> y(x, new int);
std::cout << x.get() << std::endl;
std::cout << y.get() << std::endl;
std::cout << x.use_count() << std::endl;
std::cout << y.use_count() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
你会得到这个:
0x8c66008
0x8c66030
2
2
Run Code Online (Sandbox Code Playgroud)
请注意,指针是分开的,但它们都声称具有use_count2(因为它们共享同一对象的所有权).
因此,所int拥有的x将存在只要x 或 即将存在y.如果我理解文档是正确的,那么第二个int永远不会被破坏.我通过以下测试程序证实了这一点:
struct T {
T() { std::cout << …Run Code Online (Sandbox Code Playgroud) 就在最近,我将项目的语言切换为使用C++.使用C语言,我使用了malloc,然后检查malloc是否成功但是使用C++,我使用'new'来分配内存,我想知道你是怎么做的通常会检查内存分配失败.
从我的谷歌搜索,我看到如下所示.
char *buf = new (nothrow)char[10];
Run Code Online (Sandbox Code Playgroud)
我也看到了以下内容.
try{} catch(bad_alloc&) {}
Run Code Online (Sandbox Code Playgroud)
但是下面呢?我正在使用一些chrome库例程来使用智能指针.
例如,我有如下代码.
scoped_array<char> buf(new char[MAX_BUF]);
Run Code Online (Sandbox Code Playgroud)
使用智能指针很棒,但我不确定如何检查内存分配是否成功.我是否需要使用nothrow或try/catch分成两个单独的语句?你通常如何在C++中进行这些检查?
任何建议将被认真考虑.
smart-pointers ×10
c++ ×9
boost ×5
c++11 ×5
shared-ptr ×5
atomic ×1
memory-leaks ×1
unique-ptr ×1
wrapper ×1