通常,当创建指向对象的指针并从函数返回时,您使用 unique_ptr 使用它以确保它在作用域结束时被删除。
CustomType* GetTheObject(); // Let's say this the function signature and it returns a new object
void Main() {
auto object = make_unique(GetTheObject());
object->DoSomething();
// Then the object is deleted automatically
}
如果函数签名是这样的怎么办
bool GetTheObject(CustomType** object);
我可以想象一种相当冗长的消费方式
void Main() {
// Declare a pointer which we never need
CustomType* object_ptr;
if(GetTheObject(&object_ptr)) {
// Then create a unique_ptr out of it
auto object = make_unique(object_ptr);
object->DoSomething();
// Then the object is deleted automatically
}
}
在这种情况下,是否有更好的推荐方式来使用对象。我可以考虑另一个实现 & 运算符的 unique_ptr2 类,然后像这样使用它
unique_ptr2 object;
if(GetTheObject(&object)) {
// use it
}
是否有一个可以使用的 unique_ptr2 实现来允许这样做?感觉还是不太理想。有没有更好的办法?
最佳答案
我可能很想编写代码来自动与唯一 ptr 进行转换。我们从现有函数“自动”生成一个具有相同签名的新函数,但是 T*
返回值为 unique_ptr<T>
和 T**
参数是 unique_ptr<T>*
论据。
然后我们使用 RAII 和模板元编程注入(inject)转换样板。
一个 ptr_filler
是一种 RAII 类型,可以转换 unique_ptr<T>*
变成 T**
:
template<class T>
struct ptr_filler {
std::unique_ptr<T>* output = nullptr;
T* temporary = nullptr;
ptr_filler( std::unique_ptr<T>* bind ):output(bind) {}
operator T**()&&{return &temporary;}
~ptr_filler() {
if (temporary)
*output = std::unique_ptr<T>(temporary);
}
};
ret_converter_t
执行从 C 风格 API 到 C++ unique-ptr API 的类型转换:template<class T> struct ret_converter { using type=T; };
template<class T> using ret_converter_t = typename ret_converter<T>::type;
template<class T> struct ret_converter<T*> { using type=std::unique_ptr<T>; };
get_converter_t
将 C 风格 API 的参数类型转换为通过 ptr_filler
填充唯一 ptrs 的类型:template<class T> struct get_converter { using type=T; };
template<class T> using get_converter_t = typename get_converter<T>::type;
template<class T> struct get_converter<T**> { using type=ptr_filler<T>; };
最后,
call
从您传递给它的函数指针中推断出它的参数,然后将参数和 retval 转换为使用唯一的 ptr 内存管理,并调用函数 f
为你:template<class R, class...Args>
ret_converter_t<R> call( R(* f)(Args...), get_converter_t<Args>... args ) {
return static_cast<ret_converter_t<R>>( f( std::forward<decltype(args)>(args)... ) );
}
现在我们可以:
struct CustomType {
int x;
};
CustomType* GetTheObject(int x) { return new CustomType{x}; }
bool MakeTheObject( CustomType** pp, int a, int b ) { *pp = new CustomType{a+b}; return a>b; }
我们能做的:
int main() {
std::unique_ptr<CustomType> ptr;
std::cout << call( MakeTheObject, &ptr, 2, 1 ) << " = 1\n";
std::cout << ptr->x << " = 3\n";
ptr = call( GetTheObject, 7 );
std::cout << ptr->x << " = 7\n";
}
您可以通过
call<MakeTheObject>
获得更高级的体验语法,但它需要工作。这假定您要包装的 API 是 C-ish API,但返回 new
'd 对象。Live example .
关于c++ - 使用作为参数返回的指针的最佳实践是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59291552/