传递shared_ptr的最佳做法是什么?
目前我传递shared_ptr函数参数,如下所示:
void function1( shared_ptr<TYPE>& value );
Run Code Online (Sandbox Code Playgroud) 我在整个应用程序中广泛使用std :: tr1 :: shared_ptr.这包括在函数参数中传递对象.考虑以下:
class Dataset {...}
void f( shared_ptr< Dataset const > pds ) {...}
void g( shared_ptr< Dataset const > pds ) {...}
...
Run Code Online (Sandbox Code Playgroud)
虽然通过shared_ptr传递数据集对象可以保证它在f和g中的存在,但是这些函数可能会被调用数百万次,这会导致很多shared_ptr对象被创建和销毁.这是最近一次运行的平坦gprof配置文件的片段:
Each sample counts as 0.01 seconds. % cumulative self self total time seconds seconds calls s/call s/call name 9.74 295.39 35.12 2451177304 0.00 0.00 std::tr1::__shared_count::__shared_count(std::tr1::__shared_count const&) 8.03 324.34 28.95 2451252116 0.00 0.00 std::tr1::__shared_count::~__shared_count()
因此,大约17%的运行时用于使用shared_ptr对象进行引用计数.这是正常的吗?
我的应用程序的很大一部分是单线程的,我正在考虑重写一些函数
void f( const Dataset& ds ) {...}
Run Code Online (Sandbox Code Playgroud)
并替换电话
shared_ptr< Dataset > pds( new Dataset(...) );
f( pds …Run Code Online (Sandbox Code Playgroud) 当比较两个指针变体 - 经典与shared_ptr时 - 我对程序运行速度的显着提高感到惊讶.为了测试2D Delaunay增量插入算法已被使用.
编译器设置:
VS 2010(发布)/ O2/MD/GL,W7 Prof,CPU 3.GHZ DualCore
结果:
shared_ptr(C++ 0x00):
N[points] t[sec]
100 000 6
200 000 11
300 000 16
900 000 36
Run Code Online (Sandbox Code Playgroud)
指针:
N[points] t[sec]
100 000 0,5
200 000 1
300 000 2
900 000 4
Run Code Online (Sandbox Code Playgroud)
shared_ptr版本的运行时间大约是其10倍.这是由编译器设置引起的还是C++ 0x00 shared_ptr实现那么慢?
VS2010 Profiler:对于原始指针,大约60%的时间花费在启发式搜索包含插入点的三角形上(这是一个众所周知的事实).但是对于shared_ptr版本,大约58%的时间花在使用shared_ptr.reset()上,只有10%用于启发式搜索.
void DT2D::DT ( Node2DList *nl, HalfEdgesList *half_edges_dt, bool print )
{
// Create 2D Delaunay triangulation using incremental insertion method
unsigned int nodes_count_before = nl->size();
// Remove duplicit points …Run Code Online (Sandbox Code Playgroud) 我已经远离严肃的C++大约十年了.我正在重新回到目前,我正在开展一个项目,以完全熟悉C++ 11.我有一个关于如何最好地传递std :: shared_ptr的存在主义危机.
举一个简单的例子,采取以下设置:
class ServiceB {
public:
ServiceB() {}
};
class ServiceA {
public:
ServiceA(std::shared_ptr<ServiceB>& serviceB)
: _serviceB(serviceB) {
}
private:
std::shared_ptr<ServiceB> _serviceB;
};
class Root {
public:
Root()
: _serviceB(std::shared_ptr<ServiceB>(new ServiceB())),
_serviceA(std::unique_ptr<ServiceA>(new ServiceA(_serviceB))) {
}
private:
std::shared_ptr<ServiceB> _serviceB;
std::unique_ptr<ServiceA> _serviceA;
};
Run Code Online (Sandbox Code Playgroud)
请注意,ServiceA需要引用ServiceB.我想将该引用保存在shared_ptr中.我可以做我在这里做的事情,这只是将shared_ptr作为参考传递下去,让std :: shared_ptr复制构造函数为我工作吗?这是否正确地增加了shared_ptr上的引用计数?
如果这不是最好的方法,那么传递std :: shared_ptr的常见"最佳实践"是什么?
以下是关于创建Stuff和赋予它Foo所有权的合理有效的方法吗?
class Foo
{
explicit Foo(const std::shared_ptr<Stuff>& myStuff)
: m_myStuff(myStuff)
{
}
...
private:
const std::shared_ptr<Stuff> m_myStuff;
}
std::shared_ptr<Stuff> foosStuff(new Stuff());
Foo f(foosStuff);
Run Code Online (Sandbox Code Playgroud) 我试图找到答案一段时间,但我失败了.
让我们假设我们有一个shared_ptr从一个线程创建.然后我们将它传递shared_ptr给另外2个线程(例如使用一些队列).所以从这一刻开始,有两份原件shared_ptr,指向同一个原始指针.两个所有者线程都shared_ptr将从队列中获取它们的副本.然后他们会将它传递给另一个线程或将其销毁.
问题是 - 它安全吗?原始指针是否会被正确销毁(没有竞争引用计数器?)

考虑以下向量:
std::vector<std::shared_ptr<X>> myVector;
Run Code Online (Sandbox Code Playgroud)
以及以下两个将给定元素添加到向量的函数:
void foo1(std::shared_ptr<X> x)
{
myVector.push_back(x);
}
void foo2(const std::shared_ptr<X>& x)
{
myVector.push_back(x);
}
Run Code Online (Sandbox Code Playgroud)
我的理解是,这两个函数都将 a 推shared_ptr入X向量中,从而增加 的引用计数X。第一个函数导致引用计数的额外递增和递减,但这是不必要的。
我的理解正确吗?那么第二种选择是否更可取呢?
c++ reference-counting pass-by-value shared-ptr pass-by-const-reference
假设我有一个类,其中包含一个智能指针作为其成员变量:
class B;
class A {
public:
A(const std::shared_ptr<B>& b) : b_(b) {} // option1: passing by reference
A(std::shared_ptr<B> b) : b_(b) {} // option2: passing by value
std::shared_ptr<B> b_;
};
Run Code Online (Sandbox Code Playgroud)
我对A的构造函数有两种选择:通过智能指针构造和通过智能指针的引用构造。
这两种方法各有什么优缺点?
复制智能指针是浪费吗?
有人对如何boost::shared_ptr通过价值或参考传递任何理想.
在我的平台(32位)sizeof(shared_ptr)等于8个字节,看起来我应该通过引用传递它们,但也许有人有另一个意见/做了一个配置文件/类似的东西?
我想写一个看起来像这样的函数:
template<class T>
void Foo(const std::shared_ptr<const T>& ptr);
Run Code Online (Sandbox Code Playgroud)
所以我可以这样称呼它:
std::shared_ptr<int> ptr;
Foo(ptr);
Run Code Online (Sandbox Code Playgroud)
但是,编译器无法推断T,我必须明确它:
Foo<int>(ptr);
Run Code Online (Sandbox Code Playgroud)
或者用它重载void Foo(const std::shared_ptr<T>& ptr).
我可以有一个单一的声明Foo,const T以便T可以推断出来吗?