在C++ 11上找不到多少,但仅限于提升.
考虑以下课程:
class State
{
std::shared_ptr<Graph> _graph;
public:
State( const State & state )
{
// This is assignment, and thus points to same object
this->_graph = std::make_shared<Graph>( state._graph );
// Deep copy state._graph to this->_graph ?
this->_graph = std::shared_ptr<Graph>( new Graph( *( state._graph.get() ) ) );
// Or use make_shared?
this->_graph = std::make_shared<Graph>( Graph( *( state._graph.get() ) ) );
}
};
Run Code Online (Sandbox Code Playgroud)
假设类Graph有一个复制构造函数:
Graph( const Graph & graph )
Run Code Online (Sandbox Code Playgroud)
我不想有这个 - > _ graph point/share同一个对象!相反,我希望这个 …
我正在考虑使用"自杀对象"来模拟游戏中的实体,即能够自行删除的对象.现在,一般的C++ 03的实现(普通旧delete this)不执行任何潜在指的自杀的对象,这就是为什么我使用的其他对象std::shared_ptr和std::weak_ptr.
现在进行代码转储:
#include <memory>
#include <iostream>
#include <cassert>
struct SuObj {
SuObj() { std::cout << __func__ << '\n'; }
~SuObj() { std::cout << __func__ << '\n'; }
void die() {
ptr.reset();
}
static std::weak_ptr<SuObj> create() {
std::shared_ptr<SuObj> obj = std::make_shared<SuObj>();
return (obj->ptr = std::move(obj));
}
private:
std::shared_ptr<SuObj> ptr;
};
int main() {
std::weak_ptr<SuObj> obj = SuObj::create();
assert(!obj.expired());
std::cout << "Still alive\n";
obj.lock()->die();
assert(obj.expired());
std::cout << "Deleted\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
此代码似乎工作正常.但是,我想让别人去关注它.这段代码有意义吗?我是否盲目地驶入未定义的土地?我应该放弃键盘并立即开始艺术研究吗?
我希望这个问题能够充分缩小.看起来有点微小而且低级别的CR. …
我们有一个C++库,我们提供给几个不同的客户端.最近我们改用了在公共接口中使用原始指针而不是使用boost :: sharedptr.正如您可能猜到的那样,这提供了巨大的好处,因为现在客户不再需要担心谁需要删除什么以及何时删除.当我们进行切换时,我认为这是正确的做法,但是让我感到困扰的是我们必须在公共界面中包含来自第三方库的内容 - 如果可以的话,通常会避免这种情况.我认为提升实际上是C++语言的一部分,我们的用例要求客户端代码和库都保存指向对象的指针.然而,最近我们的一位客户问我们是否可以在界面中切换到使用中性智能指针类,因为我们的图书馆实际上是强迫他们使用特定版本的提升 - 这一点我当然理解和欣赏.所以现在我想知道什么是最好的行动方案.我已经考虑了一下,并想知道如何创建一个简单的智能指针类,它只是一个真正的提升智能指针.但是客户端可能会立即将其中一个填充到boost :: sharedptr中,然后我们将深入分析三个 - 这可能是一个问题,或者可能不是.无论如何,我很想听听社区关于解决这个问题的最佳方法的一些意见.我已经考虑了一下,并想知道如何创建一个简单的智能指针类,它只是一个真正的提升智能指针.但是客户端可能会立即将其中一个填充到boost :: sharedptr中,然后我们将深入分析三个 - 这可能是一个问题,或者可能不是.无论如何,我很想听听社区关于解决这个问题的最佳方法的一些意见.我已经考虑了一下,并想知道如何创建一个简单的智能指针类,它只是一个真正的提升智能指针.但是客户端可能会立即将其中一个填充到boost :: sharedptr中,然后我们将深入分析三个 - 这可能是一个问题,或者可能不是.无论如何,我很想听听社区关于解决这个问题的最佳方法的一些意见.
编辑:我原先说的是所有权的转移,但是我应该指定API边界两侧的代码需要保存一个指向该对象的指针.
我需要编写一个复制构造函数,深度复制一个内容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谈论它之外,但他们从未提及为什么会这样.
我需要经常做这样的事情:
AsyncOperation * pAsyncOperation = new AsyncOperation();
auto bindOperation = std::bind(&AsyncOperation::operator(), std::ref(*pAsyncOperation));
std::thread thread(bindOperation );
thread.join();
Run Code Online (Sandbox Code Playgroud)
与AsyncOperation任何自定义类实现operator() (也称为函子或函数对象).
是否可以指示std::bind使用std::shared_ptr而不是std::ref?这样可以防止内存泄漏,而不需要保持引用pAsyncOperation,并且会AsyncOperation在线程结束时自动删除,即此异步任务的结束.
编辑:我并不总是有权访问std :: thread,线程库可以是boost :: thread甚至任何其他平台相关的线程.结果,不能访问std :: async.
我的主要问题是在std :: bind中拥有一个占有概念.
考虑以下代码:
#include <memory>
#include <iostream>
using namespace std;
struct MySharedStruct
{
int i;
};
void print_value_of_i(weak_ptr<MySharedStruct> weakPtr)
{
if (shared_ptr<MySharedStruct> sp = weakPtr.lock())
{ cout << "Value of i = " << sp->i << endl; }
else
{ cout << "Resource has expired"; }
}
int main()
{
shared_ptr<MySharedStruct> sharedPtr(new MySharedStruct() );
sharedPtr->i = 5;
weak_ptr<MySharedStruct> weakPtr;
weakPtr = sharedPtr;
print_value_of_i(weakPtr);
sharedPtr.reset(new MySharedStruct() ); // <<----- How does weak_ptr know it has expired after this line executes?
sharedPtr->i = 10; …Run Code Online (Sandbox Code Playgroud) 很少会遇到一个不包含原始指针的类,但默认的复制构造函数是不够的.例如,当您有一个引用计数对象时.boost :: shared_ptr <>就是一个例子.
有人可以详细说明吗?如果我们有一个包含a的类boost::shared_ptr,那么当类被构造复制时,不会构造复制 - 因此shared_ptr构造函数不会做正确的事情并增加引用计数吗?例如,下面的代码Inner正确复制- 为什么这不适用shared_ptr?:
#include <iostream>
using namespace std;
class Inner
{
public:
Inner() { cout << "inner default constructed" << endl;}
Inner(const Inner& other) { cout << "inner properly copied" << endl;}
};
class Outer
{
Inner i;
};
int main() { Outer o; Outer p(o); return 0;}
Run Code Online (Sandbox Code Playgroud) 我用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) shared-ptr ×10
c++ ×9
c++11 ×5
deep-copy ×2
api ×1
atomic ×1
boost ×1
constructor ×1
ownership ×1
refcounting ×1
std ×1
stdbind ×1
weak-ptr ×1