我们有一个C++库,我们提供给几个不同的客户端.最近我们改用了在公共接口中使用原始指针而不是使用boost :: sharedptr.正如您可能猜到的那样,这提供了巨大的好处,因为现在客户不再需要担心谁需要删除什么以及何时删除.当我们进行切换时,我认为这是正确的做法,但是让我感到困扰的是我们必须在公共界面中包含来自第三方库的内容 - 如果可以的话,通常会避免这种情况.我认为提升实际上是C++语言的一部分,我们的用例要求客户端代码和库都保存指向对象的指针.然而,最近我们的一位客户问我们是否可以在界面中切换到使用中性智能指针类,因为我们的图书馆实际上是强迫他们使用特定版本的提升 - 这一点我当然理解和欣赏.所以现在我想知道什么是最好的行动方案.我已经考虑了一下,并想知道如何创建一个简单的智能指针类,它只是一个真正的提升智能指针.但是客户端可能会立即将其中一个填充到boost :: sharedptr中,然后我们将深入分析三个 - 这可能是一个问题,或者可能不是.无论如何,我很想听听社区关于解决这个问题的最佳方法的一些意见.我已经考虑了一下,并想知道如何创建一个简单的智能指针类,它只是一个真正的提升智能指针.但是客户端可能会立即将其中一个填充到boost :: sharedptr中,然后我们将深入分析三个 - 这可能是一个问题,或者可能不是.无论如何,我很想听听社区关于解决这个问题的最佳方法的一些意见.我已经考虑了一下,并想知道如何创建一个简单的智能指针类,它只是一个真正的提升智能指针.但是客户端可能会立即将其中一个填充到boost :: sharedptr中,然后我们将深入分析三个 - 这可能是一个问题,或者可能不是.无论如何,我很想听听社区关于解决这个问题的最佳方法的一些意见.
编辑:我原先说的是所有权的转移,但是我应该指定API边界两侧的代码需要保存一个指向该对象的指针.
在使用智能指针的C++项目中,例如boost::shared_ptr,使用" this" 的好设计理念是什么?
考虑一下:
存储任何智能指针中包含的原始指针以供以后使用是危险的.您已放弃对对象删除的控制,并信任智能指针以在正确的时间执行此操作.
非静态类成员本质上使用this指针.它是一个原始指针,无法更改.
如果我存储this在另一个变量或把它传递给这有可能保存它供以后或在回调绑定它的另一个功能,我创建的引入当有人决定做一个共享指针,以我的课的错误.
鉴于此,我何时适合明确使用this指针? 是否有设计范例可以防止与此相关的错误?
我在C++的应用程序中使用boost :: shared_ptr.内存问题非常严重,应用程序占用大量内存.
但是,因为我将每个新建对象放入shared_ptr,当应用程序退出时,不会检测到内存泄漏.
必须有一些像std::vector<shared_ptr<> >池持有资源的东西.调试时如何知道谁拥有shared_ptr?
很难逐行检查代码.代码太多......
非常感谢!
我需要编写一个复制构造函数,深度复制一个内容std::shared_ptr.但是,int a, b, c, d, e;在类中还定义了一堆变量.有没有办法在我的新重载的代码中生成默认的复制构造函数代码(或调用默认的复制构造函数).
这是一个带有注释的代码片段,希望能够澄清问题.
class Foo {
public:
Foo() {}
Foo(Foo const & other);
...
private:
int a, b, c, d, e;
std::shared_ptr<Bla> p;
};
Foo::Foo(Foo const & other) {
p.reset(new Bla(*other.p));
// Can I avoid having to write the default copy constructor code below
a = other.a;
b = other.b;
c = other.c;
d = other.d;
e = other.e;
}
Run Code Online (Sandbox Code Playgroud) 我有一个共享对象需要发送到系统API并稍后将其解压缩.系统API仅接收void*.我不能使用shared_ptr :: get(),因为它不会增加引用计数,并且可以在从系统API中提取之前由其他线程释放.发送新的shared_ptr*将起作用,但涉及额外的堆分配.
一种方法是让对象派生自enable_shared_from_this.但是,因为此类模板仅拥有weak_ptr,所以仅保持释放对象是不够的.
所以我的解决方案如下所示:
class MyClass:public enable_shared_from_this<MyClass> {
private:
shared_ptr<MyClass> m_this;
public:
void *lock(){
m_this=shared_from_this();
return this;
}
static shared_ptr<MyClass> unlock(void *p){
auto pthis = static_cast<MyClass *>(p);
return move(pthis->m_this);
}
/* ... */
}
/* ... */
autp pobj = make_shared<MyObject>(...);
/* ... */
system_api_send_obj(pobj->lock());
/* ... */
auto punlocked = MyClass::unlock(system_api_reveive_obj());
Run Code Online (Sandbox Code Playgroud)
有没有更简单的方法来做到这一点?
这个解决方案的缺点:
除了基类中shared_ptr<MyClass>的a 之外,它还需要在MyClass对象布局中添加一个.weak_ptrenable_shared_from_this
正如我在评论中提到的,访问lock()和unlock()同时不安全.
最糟糕的是,这个解决方案只能lock()在呼叫之前支持一次unlock().如果要将同一对象用于多个系统API调用,则必须实现其他引用计数.
如果我们有另一个enable_lockable_shared_from_this类,那将是更大的:
class MyClass:public enable_lockable_shared_from_this<MyClass> {
/* ... …Run Code Online (Sandbox Code Playgroud) 我有一个问题,理解为什么shared_ptr使用原子CPU指令...我无法弄清楚原因,因为它不是线程安全的.有人可以解释一下.
如果你想知道我是如何知道它使用原子intstuructions:有一个来自C++的剪辑,除了Herb和Andrei谈论它之外,但他们从未提及为什么会这样.
有时我需要shared_ptr具有no-op删除器的shared_ptr实例,因为API需要一个它想要在有限时间内存储的实例但我得到一个原始指针,我不允许拥有的时间比我正在运行的时间大对于.
对于这种情况,我一直用一个空操作删除器,如[](const void *){},但今天我发现还有另一种选择到,使用(或滥用?)的混叠构造的shared_ptr:
void f(ExpectedClass *ec) {
std::shared_ptr<ExpectedClass> p(std::shared_ptr<void>(), ec);
assert(p.use_count() == 0 && p.get() != nullptr);
apiCall(p);
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,更好的方法是什么?为什么?性能期望是否相同?使用no-op删除器,我希望为删除器和引用计数的存储支付一些费用,当使用带有空的别名构造函数时似乎不是这种情况shared_ptr.
在我尝试了很多事情之前问过这个问题并发现问题与glutInit有关.请使用以下代码示例:main.cpp
#include <iostream>
#include <memory>
#include<GL/glut.h>
using namespace std;
int main(int argcp, char **argv)
{
shared_ptr<double> abc;
glutInit(&argcp,argv);
cout<<"Hello!"<<endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译:
g ++ -std = c ++ 11 -g -Wall -o appx main.cpp -lGL -lGLU -lglut
导致可执行文件使用g ++ 5.2.1,ubuntu 15.10使用segfault立即崩溃(没有"Hello!"输出)
只是评论出这条线
shared_ptr<double> abc;
Run Code Online (Sandbox Code Playgroud)
将解决崩溃.
由于我想在项目中使用shared_ptr和glut,我想知道如何修复它或导致崩溃的原因.
编辑1: GDB跟踪:
#0 0x0000000000000000 in ?? ()
#1 0x00007ffff33fb6fd in init () at dlerror.c:177
#2 _dlerror_run (operate=operate@entry=0x7ffff33fb0e0 <dlsym_doit>,args=args@entry=0x7fffffffde00) at dlerror.c:129
#3 0x00007ffff33fb148 in __dlsym (handle=<optimized out>, name=optimized out>) at dlsym.c:70
#4 …Run Code Online (Sandbox Code Playgroud) 在C++ 11和C++ 14中,
std::shared_ptr<T>从以下构造a是有效的std::unique_ptr<T[]>:Run Code Online (Sandbox Code Playgroud)std::unique_ptr<int[]> arr(new int[1]); std::shared_ptr<int> ptr(std::move(arr));由于
shared_ptr从中获取其删除(std::default_delete<T[]>对象)unique_ptr,因此将正确地释放数组.在C++ 17中不再允许这样做.而
std::shared_ptr<T[]>应该使用数组形式 .
为什么在C++ 17中不允许这样做?发生了什么变化?
我用c ++实现了二叉搜索树.而不是使用裸指针指向我使用的节点的孩子std::shared_ptr.树的节点如下实现
struct treeNode;
typedef std::shared_ptr<treeNode> pTreeNode;
struct treeNode {
T key;
pTreeNode left;
pTreeNode right;
treeNode(T key) : key(key), left(nullptr), right(nullptr) {}
};
Run Code Online (Sandbox Code Playgroud)
从BST中删除节点时,其中一种情况是节点只有一个子节点.该子节点简单地替换该节点,如下所示:
| remove node
node ---------> |
\ right
right
Run Code Online (Sandbox Code Playgroud)
在类似的Java实现中,这可以编码为:
node = node.getRight();
Run Code Online (Sandbox Code Playgroud)
在我的C++实现中,它是:
node = node->right;
Run Code Online (Sandbox Code Playgroud)
其中node是type pTreeNode.
在pTreeNode(std::shared_ptr<TreeNode>)上调用=运算符时,node将调用析构函数.指向底层的共享指针的数量TreeNode是1,因此TreeNode被破坏释放其内存.当TreeNode(默认)调用析构函数,每个成员都毁灭了.这肯定会导致pTreeNode right成员被摧毁.问题node->right在于分配给的是什么node.在测试我的BST时,它似乎工作正常,没有错误/内存泄漏.
我认为可能有用的"黑客"是制作另一个指针以增加其引用计数.这是一个适当的解决方案吗?
//increase reference to node->right by 1 so it doesn't get …Run Code Online (Sandbox Code Playgroud) c++ ×10
shared-ptr ×10
c++11 ×5
boost ×2
api ×1
atomic ×1
c++17 ×1
constructor ×1
deep-copy ×1
gcc ×1
glut ×1
memory-leaks ×1
pointers ×1
this ×1