有没有之间的差异boost::shared_ptr,std::tr1::shared_ptr以及即将到来的(中C++0x)std::shared_ptr?
从一个移植到另一个有任何开销还是基本相同?
我们已经转移到使用boost::shared_ptr所有代码,但是我们仍然有一些我们使用的孤立案例std::auto_ptr,包括单例类:
template < typename TYPE >
class SharedSingleton
{
public:
static TYPE& Instance()
{
if (_ptrInstance.get() == NULL)
_ptrInstance.reset(new TYPE);
return *_ptrInstance;
}
protected:
SharedSingleton() {};
private:
static std::auto_ptr < TYPE > _ptrInstance;
};
Run Code Online (Sandbox Code Playgroud)
我被告知有一个很好的理由说明为什么没有这个shared_ptr,但对于我的生活,我不明白为什么?我知道auto_ptr最终会在下一个标准中被标记为折旧,所以我想知道我可以用什么/如何替换这个实现.
另外,你有没有其他原因考虑使用auto_ptr而不是shared_ptr?你认为将来有什么问题转移到shared_ptr吗?
编辑:
auto_ptr与shared_ptr在上面的代码",答案是肯定的-但我会带一个小的性能损失.auto_ptr最终标记为折旧并且我们转向时std::shared_ptr,我们需要彻底测试我们的代码以确保我们遵守不同的所有权语义.std :: shared_ptr构造函数的行为不符合我的预期:
#include <iostream>
#include <vector>
void func(std::vector<std::string> strings)
{
for (auto const& string : strings)
{
std::cout << string << '\n';
}
}
struct Func
{
Func(std::vector<std::string> strings)
{
for (auto& string : strings)
{
std::cout << string << '\n';
}
}
};
int main(int argc, const char * argv[])
{
func({"foo", "bar", "baz"});
Func({"foo", "bar", "baz"});
//auto ptr = std::make_shared<Func>({"foo", "bar", "baz"}); // won't compile.
//auto ptr = std::make_shared<Func>{"foo", "bar", "baz"}; // nor this.
return 0;
} …Run Code Online (Sandbox Code Playgroud) 几天前,我碰巧看到Stephan T. Lavavej的这个非常有趣的演讲,提到了" 我们知道你住在哪里 "的优化(抱歉使用问题标题中的首字母缩略词,所以SO警告我这个问题可能已被关闭,否则),这是Herb Sutter在机器架构上的精彩之作.
简而言之," 我们知道你住在哪里 "的优化包括将引用计数器放在与make_shared正在创建的对象相同的内存块上,从而产生一个单独的内存分配而不是两个并使其shared_ptr更紧凑.
总结我从上面的两个报告后得知,但是,我开始怀疑WKWYL优化是否可以不降低性能的情况下,shared_ptr被多个线程访问在不同内核上运行.
如果引用计数器接近内存中的实际对象,实际上它们应该更有可能被提取到与对象本身相同的高速缓存行中.反过来,如果我正确地得到了这个教训,那么即使在他们不需要时,线程也会在竞争同一个缓存行时减慢速度.
假设其中一个线程需要多次更新引用计数器(例如,当复制shared_ptr周围时),而其他线程只需要访问指向的对象:这不会通过使它们竞争来减慢所有线程的执行速度对于相同的缓存行?
如果refcount存在于内存中的其他位置,我会说争用不太可能出现.
这对于make_shared()在类似情况下使用是否是一个很好的论据(当然,只要它实现了WKWYL优化)?或者我的推理中有谬误吗?
以下是一些代码段.
std::shared_ptr<int> global(new int(1));
void swapper(int x)
{
std::shared_ptr<int> sp(new int(x));
global.swap(sp);
}
Run Code Online (Sandbox Code Playgroud)
假设我想调用swapper并行线程.这是线程安全的吗?
我知道这个答案.它显示了如果我重新分配值,如何指定指针不是线程安全的global.
我的问题是swap成员函数本身是否是线程安全的.
一方面,shared_ptr的控制块功能是线程安全的.另一方面,我假设我正在切换到控制块的指针,所以它不应该是线程安全的.
有什么联系?是swap线程安全的?
我知道在一个模块中创建新东西并在另一个模块中删除它通常会导致VC++出现问题.运行时间不同的问题.如果我没记错的话,将模块与静态链接的运行时混合和/或动态链接的版本不匹配都可以搞砸了.
但是,跨模块使用VC++ 2008的std :: tr1 :: shared_ptr是否安全?
由于只有一个版本的运行时甚至知道什么是shared_ptr,静态链接是我唯一的危险(现在......).我以为我已经读过boost的版本的shared_ptr可以安全使用,但是我使用的是Redmond的版本......
我试图避免在分配模块中对自由对象进行特殊调用.(或类似于"删除此"本身).如果这一切看起来有点hacky,我正在使用它进行单元测试.如果您曾经尝试对现有的C++代码进行单元测试,那么您可以了解有时需要创造性.我的内存由EXE分配,但最终将在DLL中释放(如果引用计数按我认为的方式工作).
class MyClass {
public:
MyClass(std::weak_ptr<MyClass> parent){}
}
Run Code Online (Sandbox Code Playgroud)
我想做这个:
auto newInstance = std::make_shared<MyClass>(nullptr);
Run Code Online (Sandbox Code Playgroud)
或者weak_ptr参数的默认值为null,例如:
void function(int arg,std::weak_ptr<MyClass> obj = nullptr);
Run Code Online (Sandbox Code Playgroud)
但是,我需要的是这样做:
auto newInstance = std::make_shared<MyClass>(std::shared_ptr<MyClass>(nullptr));
Run Code Online (Sandbox Code Playgroud)
这是为什么?
我从Objective-C背景来到C++ 11,而我正在努力解决的一件事是C++ 11 lambdas与Objective-C"blocks"的不同捕获语义.(见这里进行比较).
在Objective-C中,与C++一样,如果引用成员变量,则会隐式捕获self/ this指针.但是因为Objective-C中的所有对象都是有效的"共享指针",所以要使用C++术语,你可以这样做:
doSomethingAsynchronously(^{
someMember_ = 42;
});
Run Code Online (Sandbox Code Playgroud)
...并确保在执行块时,您正在访问其成员的对象将处于活动状态.你不必考虑它.C++中的等价物似乎是这样的:
// I'm assuming here that `this` derives from std::enable_shared_from_this and
// is already owned by some shared_ptr.
auto strongThis = shared_from_this();
doSomethingAsynchronously([strongThis, this] {
someMember_ = 42; // safe, as the lambda holds a reference to this
// via shared_ptr.
});
Run Code Online (Sandbox Code Playgroud)
在这里,您需要记住除了this指针之外还要捕获shared_ptr.是否有一些不那么容易出错的方法来实现这一目标?
我想知道是否有可能为任何"常见"架构(如x64或ARMv7/ARMv8)创建无锁,线程安全的共享指针.
在cppcon2014上关于无锁编程的讨论中,Herb Sutter提出了一个无锁定单链表的(部分)实现.实现看起来很简单,但它依赖于shared_ptr标准库中不存在或使用专用std::atomic...函数的原子实现.这一点尤为重要,因为单个push/pop调用可能会调用多个原子加载/存储和compare_exchange操作.
我看到的问题(我认为谈话中的一些问题是朝着相同的方向)是因为这是一个实际的无锁数据结构,那些原子操作本身就必须是无锁的.我不知道任何标准库实现std::atomic...的无锁功能 - 至少有一个简短的google/SO搜索 - 我也没有找到如何实现无锁专业化的建议std::atomic<std::shared_ptr>.
在我浪费时间之前,我想问:
std::atomic<std::shared_ptr>?对于所提到的队列,它尤其需要CAS操作.供参考,这里是来自Herb Sutter的代码(可能包含来自我的错别字):
template<class T>
class slist {
struct Node { T t; std::shared_ptr<Node> next; };
std::atomic<std::shared_ptr<Node>> head;
public:
class reference{
std::shared_ptr<Node> p;
public:
reference(std::shared_ptr<Node> p_){}
T& operator*(){ return p->t; }
T* operator->(){ return &p->t; }
};
auto find(T t) const {
auto p = head.load();
while …Run Code Online (Sandbox Code Playgroud)