我有以下代码在Objective-C函数Datum
中使用类work
的C ++对象:
void work(const Datum &datum) {
dispatch_async(dispatch_get_main_queue(), ^{
// Work with datum.
});
}
使用实际为boost::shared_ptr<Datum>
的实例调用此代码,即
boost::shared_ptr<Datum> the_datum(new Datum());
work(*the_datum);
在这种情况下,在the_datum
内运行块之前,实例work
可能会被释放(对dispatch_async
的调用会对datum
执行异步操作稍后执行;调用以及函数work
立即返回)。这显然会导致灾难。
一种解决方案可能是不传递对work
的引用,而是传递boost::shared_ptr<Datum>
。但是可能存在优选参考的情况,参见例如this thread。有没有办法保持work
的接口(即传递datum
作为参考),但仍然阻止在块完成之前重新分配共享指针?
答案 0 :(得分:3)
将接口保持为work()
并将其传递给datum
,无法实现此目的。无法使用datum
来防止引用计数递减。考虑以下错误程序:
#include <memory>
int main () {
std::shared_ptr<int> p1(new int);
int &x = *p1;
std::shared_ptr<int> p2(&x);
}
此代码因双重释放而崩溃,因为shared_ptr<>
控件结构不遵循指向对象的指针,而是跟随shared_ptr<>
本身。
您可以做的是更改work()
以获取shared_ptr()
,但是将更多代码添加到传递给dispatch_async()
的块中,以便它可以使用该代码中的引用。由于您要将所有权转移到异步例程,因此应使用unique_ptr<>
。我知道关于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.
});
}
答案 1 :(得分:1)
您必须自己管理参考文献:
#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;
}
答案 2 :(得分:0)
您希望转让所有权,使用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));