当使用pImpl习语时,最好使用a boost:shared_ptr而不是std::auto_ptr?我确定我曾经读过增强版更加异常友好吗?
class Foo
{
public:
Foo();
private:
struct impl;
std::auto_ptr<impl> impl_;
};
class Foo
{
public:
Foo();
private:
struct impl;
boost::shared_ptr<impl> impl_;
};
Run Code Online (Sandbox Code Playgroud)
[编辑]使用std :: auto_ptr <>是否总是安全的,或者是否需要使用替代的boost智能指针?
在过去的两年里,我一直在我的项目中广泛使用智能指针(boost :: shared_ptr).我理解并欣赏他们的好处,我一般都喜欢他们.但是我越是使用它们,我就越想念C++的确定性行为,关于内存管理和RAII,我似乎更喜欢编程语言.智能指针简化了内存管理的过程并提供了自动垃圾收集等功能,但问题是一般使用自动垃圾收集和智能指针特别引入了(de)初始化顺序的某种程度的不确定性.这种不确定性使控制权远离程序员,并且正如我最近意识到的那样,它完成了设计和开发API的工作,
为了详细说明,我目前正在开发一个API.此API的某些部分要求在其他对象之前初始化或销毁某些对象.换句话说,(de)初始化的顺序有时很重要.举个简单的例子,假设我们有一个名为System的类.系统提供一些基本功能(在我们的示例中记录)并通过智能指针保存许多子系统.
class System {
public:
boost::shared_ptr< Subsystem > GetSubsystem( unsigned int index ) {
assert( index < mSubsystems.size() );
return mSubsystems[ index ];
}
void LogMessage( const std::string& message ) {
std::cout << message << std::endl;
}
private:
typedef std::vector< boost::shared_ptr< Subsystem > > SubsystemList;
SubsystemList mSubsystems;
};
class Subsystem {
public:
Subsystem( System* pParentSystem )
: mpParentSystem( pParentSystem ) {
}
~Subsystem() {
pParentSubsystem->LogMessage( "Destroying..." );
// Destroy this subsystem: deallocate memory, release resource, etc.
} …Run Code Online (Sandbox Code Playgroud) 我遇到了这个问题并阅读它最终让我看到了boost::detail::spinlock_pool.
其目的boost::detail::spinlock_pool是spinlock通过在shared_ptrs地址上进行散列选择s 数组来减少对全局自旋锁的潜在争用.这似乎是一个合理的解决方案,但目前(Boost v1.49)版本的实现似乎存在问题.
spinlock_pool管理静态分配的41个spinlock实例的数组.看来,sizeof(spinlock)==4对于我所看到的平台 - 这意味着,例如x64与64字节spinlock的高速缓存行,每个高速缓存行将有16 秒.
即整个阵列跨越所有2 1/2缓存线.
也就是说,有一个随机螺旋锁错误共享的可能性为40%.
......首先几乎完全打败了游泳池的目的.
我的分析是正确的还是我遗漏了一些重要的东西?
更新: 我终于写了一个小的基准程序:
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#include <boost/timer.hpp>
#include <iostream>
#include <vector>
#include <stdlib.h>
using namespace std;
enum { BufferSize = 1<<24, SLsPerCacheLine = 1 };
int ibuffer[BufferSize];
using boost::detail::spinlock;
size_t nslp = 41;
spinlock* pslp = 0;
spinlock& getSpinlock(size_t h)
{
return pslp[ (h%nslp) * SLsPerCacheLine ];
}
void …Run Code Online (Sandbox Code Playgroud) 我的问题shared_ptr与make_sharedC++ 11有关.我有两个向量,第一个存储智能指针,第二个存储原始指针.第一个向量就像我已经过了一样,但是vector2只是令人困惑......
#include <iostream>
#include <vector>
#include <memory>
int main() {
std::vector<std::shared_ptr<int>> vector1;
vector1.push_back(std::make_shared<int>(1));
vector1.push_back(std::make_shared<int>(2));
vector1.push_back(std::make_shared<int>(3));
std::vector<int*> vector2;
vector2.push_back(std::make_shared<int>(4).get());
vector2.push_back(std::make_shared<int>(5).get());
vector2.push_back(std::make_shared<int>(6).get());
std::cout << "vector1 values:" << std::endl;
for(auto &value: vector1) { std::cout << *value << std::endl; }
std::cout << "vector2 values:" << std::endl;
for(auto &value: vector2) { std::cout << *value << std::endl; }
return 0;
}
Run Code Online (Sandbox Code Playgroud)
vector1 values:
1
2
3
vector2 values:
6
6
6
Run Code Online (Sandbox Code Playgroud)
我意识到创建原始指针并且不尝试转换智能指针会更简单但是让我很好奇知道为什么会发生这种情况?另外为什么每次推送都会改变vector2中的所有值?
以下是我在stackoverflow中发现的一些问题,但他们没有回答我的问题,或者我不明白答案......
我试图弄清楚是否可以创建一个指向不同类型的共享指针数组.例如,类似的东西:
vector<shared_ptr<**???**>> v;
v.push_back(shared_ptr<int>(new int));
v.push_back(shared_ptr<MyClass>(new MyClass()));
Run Code Online (Sandbox Code Playgroud)
或任何其他方式通过shared_ptr而不知道其类型.
目前我正在使用glib库中的一些函数.随着glib也来了gio.glib是一个C库,因此我需要删除一些我创建的结构.
对于我创建智能指针的许多对象,例如:
std::shared_ptr<GAsyncQueue> my_queue = std::shared_ptr<GAsyncQueue>(g_async_queue_create(), g_async_queue_unref);
Run Code Online (Sandbox Code Playgroud)
为此创建了一个指向a的共享指针GAsyncQueue,这可以安全地在其生命周期结束时销毁队列.
但是,当我从gio库获取一个我不应该释放的指针时遇到问题.在下面的代码中my_connection是一个GSocketClient,它实现了(在glib中)GIOStream.
std::shared_ptr<GInputStream> my_input_stream =
std::shared_ptr<GInputStream> (
g_io_stream_get_input_stream(G_IO_STREAM(my_connection.get()))
);
Run Code Online (Sandbox Code Playgroud)
因为GIOStream上的文档提到,g_io_stream_get_input_stream()不应释放获得的指针.那是因为它归my_connection实例所有.我想为destroy对象创建一个lamda,它是共享指针对象的第二个参数.例如auto deleter = [](GInputStream* ptr) {};,然后将lambda作为detroy函数提供给共享指针,但这感觉有点愚蠢.
几个小时前我问了一个关于连接矢量的两个元素的类似问题.现在,我想让我的问题更加笼统.我们假设我们有两个double类型的对象double d1, d2.我们希望第三个object(double d3)获取值d1+d2,这样如果我们改变d1或者d2,则d3自动获得新值d1+d2.我们怎样才能用C++做到这一点?
这就是我的意思:
int main(){
double d1,d2,d3;
d1=4;
d2=7;
//some operations to make d3=d1+d2
std::cout<<d3<<endl;// I want it to print 11
d2=-4;
std::cout<<d3<<endl;//Now without any further operations between these line, it should print 0
return 0;
}
Run Code Online (Sandbox Code Playgroud)
谢谢.
请考虑以下代码:
#include <iostream>
#include <memory>
using namespace std;
class T;
std::weak_ptr<T> wptr;
class T
{
public:
T() { }
~T() {
std::cout << "in dtor" << std::endl;
std::cout << (wptr.expired() ? "expired" : "not expired") << std::endl;
}
};
int main() {
{
auto ptr = std::make_shared<T>();
wptr = ptr;
std::cout << (wptr.expired() ? "expired" : "not expired") << std::endl;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在这段代码中,我试图找出weak_ptrs在对象销毁阶段是否过期.看来是这样.输出是:
not expired
in dtor
expired
Run Code Online (Sandbox Code Playgroud)
我用gcc-5.1和ideone.
现在,我有另一个问题.我找不到任何文档说明这是标准行为.难道是保证这样的工作方式,始终?
我想保持聪明的行为std::shared_ptr.那么有没有办法将共享的void指针转换为另一种类型而不会混淆引用计数?我无法获取原始指针并从中创建新的共享指针.
我已经看到了关于这个主题的一些其他问题,但仍然没有找到答案 - 我想我错过了一些东西:
我定义了两个简单的测试类:
class TestBase
{
public:
TestBase ( ) { };
~ TestBase ( ) { };
protected:
inline virtual int getInt ( )
{
return 0;
}
};
class TestDerived : public TestBase
{
protected:
inline int getInt ( ) override
{
return 1;
}
};
Run Code Online (Sandbox Code Playgroud)
我声明了typedef来简化它们的使用 std::shared_ptr:
typedef std::shared_ptr<TestBase> spBase;
typedef std::shared_ptr<TestDerived> spDerived;
Run Code Online (Sandbox Code Playgroud)
问题:我无法编译代码以shared_ptr多态方式使用这些声明,即使base在所有这些情况下实际上是一个实例spDerived:
Run Code Online (Sandbox Code Playgroud)spBase base; spDerived derived = static_cast < spDerived > ( base );错误:没有匹配函数来调用'std :: shared_ptr :: …
shared-ptr ×10
c++ ×9
c++11 ×7
boost ×2
c++14 ×2
auto-ptr ×1
boost-thread ×1
casting ×1
gcc ×1
make-shared ×1
pointers ×1
polymorphism ×1
raii ×1
stl ×1
weak-ptr ×1