将unique_ptr存储在堆上的最简单方法是什么

What is the simplest way to stash a unique_ptr on the heap?

本文关键字:最简单 方法 是什么 unique ptr 存储      更新时间:2023-10-16

长时间的Java,第一次C++。

我正在编写一个 Java 类,它包装了一个现有的 C++ API,看起来像这样:

public class Foo implements Closeable {
    private long handle;
    public Foo(File file) {
        this.handle = Foo.openFile(file.toString());
    }
    // other methods go here...
    public void close() {
        Foo.closeFile(this.handle);
        this.handle = 0;
    }
    private static native long openFile(String file);
    private static native void closeFile(long handle);
}

我们将指向本机C++对象的指针填充到handle字段中。

问题是C++库没有给我一个指针,它给了我一个unique_ptr<Foo>。所以这必须在 openFile() 中移动到堆上(这样它就不会超出范围),然后在 closeFile() 中销毁.

无法让它工作,并且不确定我是否正确。在C++中正确执行此操作的最简单/最干净的方法是什么?

这是我目前正在做的事情:

// This holds a unique_ptr<T>, typically on the heap, until no longer needed
template <class T>
class PointerHolder {
public:
    PointerHolder(unique_ptr<T> ptr) {
        this->ptr = std::move(ptr);
    }
    T * get() const {
        return this->ptr.get();
    }
private:
    unique_ptr<T> ptr;
};
// Holder for a Foo
typedef PointerHolder<Foo> FooHolder;
jlong JNICALL
Java_Foo_openFile(JNIEnv *jenv, jclass jcls, jstring file)
{
    ...
    // Get smart pointer to native object from provided C++ library
    unique_ptr<Foo> ptr = ...
    // Save pointer on the heap until closeFile() is invoked sometime later
    const FooHolder *const holder = new FooHolder(std::move(ptr));
    // Return pointer encoded as a Java long
    return reinterpret_cast<jlong>(holder);
}
void JNICALL
Java_Foo_closeFile(JNIEnv *jenv, jclass jcls, jlong handle)
{
    // Delete pointer holder, and by extension, storage object
    delete reinterpret_cast<FooHolder *>(handle);        // CRASH HERE
}

这是对的吗?如果是这样,可以简化吗?

无论如何,现在程序在closeFile()崩溃,但我无法判断它是否崩溃,因为我做错了什么,或者我正在使用的库中有一些错误(它相对较新且有错误)。

感谢您的任何"指示"。

它可以简化。

由于您必须与Java的生命周期管理集成,因此unique_ptr对您没有任何好处。 您不妨直接管理 T 对象的生存期,而不是它的包装器(当然不是unique_ptr包装器的FooHolder包装器,用于T - 包装太多了)。

只需在unique_ptr<T>上致电release()即可获得需要delete-d的T*