[英]How to mix C++ shared pointers and object references
I have the following code that uses a C++ object of class Datum
within an Objective-C function work
: 我有以下代码在Objective-C函数
work
中使用类Datum
的C ++对象:
void work(const Datum &datum) {
dispatch_async(dispatch_get_main_queue(), ^{
// Work with datum.
});
}
This code is called with an instance that is actually a boost::shared_ptr<Datum>
, ie 使用实际上是
boost::shared_ptr<Datum>
的实例调用此代码,即
boost::shared_ptr<Datum> the_datum(new Datum());
work(*the_datum);
In this situation it is possible that the instance the_datum
gets deallocated before the block is run inside work
(the call to dispatch_async
performs an asynchronous operation on datum
that is executed later; the call and thus the function work
return immediately). 在这种情况下可能的是,该实例
the_datum
该块内运行之前被解除分配work
(调用dispatch_async
执行上一个异步操作datum
稍后执行;该呼叫,因此功能work
立即返回)。 This obviously results in a disaster. 这显然会导致灾难。
One solution might be to not pass a reference to work
, but a boost::shared_ptr<Datum>
, instead. 一种解决方案可能是不传递对
work
的引用,而是传递boost::shared_ptr<Datum>
。 But there may be situations when references are preferred, see eg this thread . 但是可能存在首选引用的情况,例如参见此线程 。 Is there any way to keep the interface of
work
(ie, pass datum
as a reference), but still prevent the deallocation of the shared pointer prior to the completion of the block? 有没有办法保持
work
接口(即传递datum
作为参考),但仍然阻止在块完成之前重新分配共享指针?
There is no way to accomplish this by leaving the interface to work()
the same, and pass in a reference to datum
. 没有办法通过使接口
work()
相同,并传入对datum
的引用来实现这一点。 There is no way to use the datum
to prevent the reference count from decrementing. 无法使用该
datum
来防止引用计数递减。 Consider the following buggy program: 考虑以下错误程序:
#include <memory>
int main () {
std::shared_ptr<int> p1(new int);
int &x = *p1;
std::shared_ptr<int> p2(&x);
}
This code crashes with a double free, because the shared_ptr<>
control structure does not follow the pointer to the object, but is followed through shared_ptr<>
itself. 此代码与double free崩溃,因为
shared_ptr<>
控制结构不遵循指向对象的指针,而是跟随shared_ptr<>
本身。
What you can do is change work()
to take a shared_ptr()
, but add some more code to the block passed to dispatch_async()
so that it can use a reference within that code. 您可以做的是更改
work()
以获取shared_ptr()
,但是将更多代码添加到传递给dispatch_async()
的块中,以便它可以使用该代码中的引用。 Since you are transferring ownership to the asynchronous routine, you should use unique_ptr<>
instead. 由于您要将所有权转移到异步例程,因此您应该使用
unique_ptr<>
。 I know zilch about Objective-C, so this syntax might be wrong: 我知道关于Objective-C的zilch,所以这种语法可能是错误的:
void work(std::unique_ptr<Datum> &datumptr_ref) {
__block std::unique_ptr<Datum> datumptr(std::move(datumptr_ref));
dispatch_async(dispatch_get_main_queue(), ^{
Datum &datum = *datumptr
// Work with datum.
});
}
You have to manage the references yourself: 您必须自己管理参考:
#include <iostream>
#include <memory>
extern "C" {
typedef struct TagShared Shared;
Shared* allocate(const std::shared_ptr<int>& ptr) {
return (Shared*) new std::shared_ptr<int>(ptr);
}
void deallocate(Shared* shared) {
delete (std::shared_ptr<int>*)shared;
}
} // extern "C"
int main()
{
std::shared_ptr<int> s(new int(1));
Shared* p = allocate(s);
// Inside Dispatch
// No C++ but similar defined for TagShared
std::cout << **(std::shared_ptr<int>*)p << std::endl;
deallocate(p);
return 0;
}
You want to transfer ownership with std::unique_ptr
something like this: 您想使用
std::unique_ptr
转移所有权 ,如下所示:
void work(std::unique_ptr<Datum> datum) {
dispatch_async(dispatch_get_main_queue(), ^{
// Work with datum.
});
}
std::unique_ptr<Datum> the_datum(new Datum());
work(std::move(the_datum));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.