7

我有以下代码Datum在 Objective-C 函数中使用类的 C++ 对象work

void work(const Datum &datum) {
    dispatch_async(dispatch_get_main_queue(), ^{
        // Work with datum.
    });
}

这段代码是用一个实际上是 a 的实例调用的boost::shared_ptr<Datum>,即

boost::shared_ptr<Datum> the_datum(new Datum());
work(*the_datum);

在这种情况下,实例可能the_datum在块内部运行之前被释放work(对dispatch_async执行异步操作datum的调用稍后执行;调用和因此函数work立即返回)。这显然会导致灾难。

一种解决方案可能是不传递对 的引用work,而是传递 a boost::shared_ptr<Datum>。但是可能存在首选引用的情况,请参见例如this thread。有什么办法可以保留的接口work(即datum作为引用传递),但仍然防止在块完成之前释放共享指针?

4

3 回答 3

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.
    });
}
于 2013-09-18T16:48:12.703 回答
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;
}
于 2013-09-18T17:29:18.760 回答
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));
于 2013-09-18T16:22:58.267 回答