简体   繁体   English

如何混合C ++共享指针和对象引用

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM