foreach循环中指针到std::unique_ptr的隐式转换
Implicit conversion of pointer to std::unique_ptr in foreach loop
我有一个api调用,它填充了一个由调用者使用的原始指针数组。此函数堆分配每个原始指针,但不分配数组。
无论API函数有多坏,我都无法更改它。
调用api函数代码如下所示:
size_t response_count = api.getResponseCount();
std::vector<Response*> responses(response_count);
api.getResponses(responses.data());
for(auto response : responses) {
// Do some processing with response
delete response;
}
我想将每个响应封装在unique_ptr中,以便在循环迭代结束时仍对其进行清理,而不必显式调用delete。理想情况下,这看起来像:
for(std::unique_ptr<Response> response : responses) {
// Do some processing with response
// No need to delete response, it will be cleaned up as it goes out of scope
}
这不会编译,因为编译器无法将指针转换为unique_ptr:error: conversion from ‘Response*’ to non-scalar type ‘std::unique_ptr<Response>’ requested
有没有办法以这种方式将容器的每个元素强制转换为智能指针,或者我需要显式删除原始指针?
与其将每个指针封装在unique_ptr
中,不如考虑使用Boostptr_vector
。
假设数据已分配,因此您实际上可以使用delete
删除它,则代码将如下所示:
size_t response_count = api.getResponseCount();
// Unfortunately, we have to define, then resize. It has a ctor that takes a size,
// but it treats that as an amount to reserve rather than an actual size.
boost::ptr_vector<Response> responses;
responses.resize(response_count);
api.getResponses(responses.c_array());
for(auto response : responses) {
// Do some processing with response
}
并且当responses
超出范围时,它将删除它所包含的指针所指向的所有对象。如有必要,可以指定一个Allocator
类,用于定义如何分配和删除对象。
参考
https://www.boost.org/doc/libs/1_71_0/libs/ptr_container/doc/ptr_container.html
虽然不是很好的实践,但您可以使用非显式构造函数从unique_ptr
派生。
template<typename P>
struct MakeUnique : std::unique_ptr<P> {
MakeUnique(P* p) : std::unique_ptr<P>(p) {}
};
然后可以这样使用:
for ( MakeUnique<Response> resp : responses ) {
...
}
可能是最接近一句话的了。请参阅此处的工作版本。
您可以为vector<response*>
创建一个包装器,用于分发唯一指针
struct wrapper{
struct iterator {
iterator( std::vector<response*>::iterator it ) : it_(it){}
friend bool operator!=( iterator const& lhs, iterator const &rhs ){ return lhs.it_ != rhs.it_; }
void operator++(){ ++it_;}
std::unique_ptr<response> operator*(){ return std::unique_ptr<response>(*it_); }
private:
std::vector<response*>::iterator it_;
};
wrapper( std::vector<response*>& rs ) : rs_{rs} {}
iterator begin() const { return iterator{rs_.begin()}; }
iterator end() const { return iterator{rs_.end()}; }
private:
std::vector<response*>& rs_;
};
然后,您可以像这样迭代响应:
for( auto resp : wrapper( responses ) ){...
}
请参阅此处的工作版本。
相关文章:
- 防止主数据类型C++的隐式转换
- 模板参数替换失败,并且未完成隐式转换
- 努力将整数转换为链表。不知道我在这里做错了什么
- HEX值到wchar_t字符(UTF-8)的转换
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将 Qvector<uint8_t> 转换为 QString
- 如何在cuSparse中使用cusparseXcoo2csr从coo转换为csc
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 在c++中使用nlohmann从类到json的转换
- 为什么我不能在不进行任何转换的情况下将浮点数放入任何类型的 ptr 中?
- 从const ptr*转换为ptr*时出现问题
- C++ 类型转换基础 PTR 到派生 PTR 保存在引用类中
- 将 lamba 隐式转换为函数 ptr 以创建类
- 为什么非常量ptr不能隐式地将ptr转换为常量作为模板中的参数
- C++双PTR到长PTR转换
- 无法将 Uchar PTR 转换为 OpenCVsharp
- 不能动态强制转换为ptr
- 函数PTR转换为带模板参数的函数
- 将派生类的ptr类型转换为ptr类型
- 将输入字符串转换为字符* <错误 Ptr>