C++ 将unique_ptr强制转换为char**以将其作为函数参数Func(char**arg)传递

C++ 将unique_ptr强制转换为char**以将其作为函数参数Func(char**arg)传递,c++,unique-ptr,C++,Unique Ptr,使用c样式char我会: void FunctionCannotBeChanged(char** pVar) { ... do something/modify the content of the buffer } int main(..) { char* buffer = NULL; Func(&buffer) } 如果我想要一个缓冲区作为唯一\u ptr std::unique_ptr<char[]> buffer; buffer = std

使用c样式
char
我会:

void FunctionCannotBeChanged(char** pVar)
{
    ... do something/modify the content of the buffer
}

int main(..)
{
    char* buffer = NULL;
    Func(&buffer)
}
如果我想要一个缓冲区作为
唯一\u ptr

std::unique_ptr<char[]> buffer;
buffer = std::make_unique<char[]>(bufferSize);
std::唯一的ptr缓冲区;
buffer=std::使_唯一(bufferSize);

将新缓冲区传递给
函数的正确方法是什么?不能通过引用更改

首先,显示的函数要求缓冲区的类型为
char*
,但您的缓冲区的类型为
unsigned char*
,类型必须匹配

该函数用于重新分配缓冲区

如果它重新分配了缓冲区,那么一旦您将其传递给函数,它就拥有该缓冲区,因此您的
unique\u ptr
不能再拥有该缓冲区,因此您需要重新分配它

这是一个图书馆,对我来说是一个黑匣子

因为库是C库,不可能(除了它是一个C++接口的C++库),重新分配内存的函数与函数<代码> > MaMax唯一> <代码>用作默认分配内存。 库必须记录分配/释放内存必须使用的函数,您必须使用这些函数来创建属于

unuqie_ptr
的缓冲区,并且
unqiue_ptr
需要使用正确的函数(例如使用自定义删除器)来释放该缓冲区

如果不相应地这样做,应用程序将遇到未定义的行为

只有在已知您使用的库以及函数的情况下,才能说明如何正确地执行此操作。或者,如果您提供了有关该函数如何重新分配内存的所有必要信息,以及根据库必须使用哪些函数进行内存分配

假设库不进行内存管理,一种可能的方法是为该库创建包装器:

库代码:

void FunctionCannotBeChanged(char** pVar);
//  allocator/free functions either provided by the library or documented by the library that those are used
char * LibraryAlloc(size_t size);
void LibraryFree(char * ptr);
您的包装:

namespace lib_wrapper {
    
    // deleter that is used to free the memory using the correct free function
    void library_deleter(char * ptr) {
        // you might need to add a check if the pointer is a null pointer
        LibraryFree(ptr);
    }
    
    // define an own unique ptr type that uses that custom deleter
    using unique_ptr = std::unique_ptr<char,decltype(&library_deleter)>;

    // define an own make_unqiue function that uses the correct allocator
    unique_ptr make_unique(size_t size) {
        return unique_ptr(LibraryAlloc(size),&library_deleter);
    }
    
    // create a wrapper function that:
    // - releases the pointer
    // - passes it to the library function
    // - and then passes the possibly changed ptr back to your unique ptr
    void FunctionCannotBeChanged(unique_ptr &ptr) {
        auto raw_ptr = ptr.release();
        ::FunctionCannotBeChanged(&raw_ptr);
        ptr.reset(raw_ptr);
    }
    
}

int main()
{
    auto buffer = lib_wrapper::make_unique(50);
    lib_wrapper::FunctionCannotBeChanged(buffer);

    return 0;
}
这取决于你


创建包装在开始时可能需要做很多工作,但会使代码更易于维护,并将陷阱转移到包装代码中的一个中心点,远离使用库的代码部分。

没有。您的函数可能会执行与
std::unique\u ptr
不兼容的操作。您需要了解哪些
功能不能更改
是允许执行的。它究竟如何修改
*pvar
?双指针使它变得非常困难。这表明函数可以重新分配数据并重新分配原始指针。这将不可能与智能指针。如果另一个对象中有数据,则需要将数据复制到新的(临时)缓冲区中,传递指向该(临时)缓冲区指针的指针,然后将数据复制回或创建新的智能指针或其他类似字符串的对象(我真的建议您对任何类似字符串的数据使用
std::string
,或者可能使用
std::vector
,而不是智能指针)。真正的信息是:避免
函数(char**)
和使用它的库(如果可以的话)。仍然要考虑所有的事情,如果需要的话,按照前面的评论中的描述去做。另外,比起
std::unique\u ptr
@branero79库文档告诉你内存是如何重新分配的吗?@branero79如果库分配内存,如何释放?是否有其他函数?感谢您的详细解释。这些问题是由于我缺乏知识以及我必须使用的库API混乱造成的。
int main()
{
    auto buffer = lib_wrapper::make_unique(50);
    buffer = lib_wrapper::FunctionCannotBeChanged(std::move(buffer));

    return 0;
}