如何解引用std::unique_ptr<int[]>?为何operator*无法使用?
解决方法
以下是几种无需调用get()获取裸指针,就能让std::unique_ptr<int[]>指向的数组作为std::ranges::transform输出目标的方案:
方案1:用std::views::iota构造可写视图
利用unique_ptr<int[]>支持的operator[],结合索引视图生成可写的元素引用序列,直接作为输出目标:
#include <ranges> #include <memory> #include <algorithm> int main() { auto ptr = std::make_unique<int[]>(5); const auto in = std::array{1, 2, 3, 4, 5}; // 生成映射到数组元素的可写视图 auto out = std::views::iota(0, 5) | std::views::transform([&](const int idx) -> int& { return ptr[idx]; }); std::ranges::transform(in, out.begin(), [](const int x) { return x * 2; }); }
这个视图会直接绑定到ptr指向的数组,所有对视图元素的写入都会同步到原数组,全程未使用裸指针。
方案2:自定义unique_ptr<int[]>的range包装器
如果需要重复使用,可以封装一个简单的range类,通过operator[]访问数组元素,无需裸指针:
#include <ranges> #include <memory> #include <algorithm> template<std::size_t ArraySize> struct UniqueArrayRange { std::unique_ptr<int[]>& arr_ptr; // 自定义前向迭代器 struct Iterator { std::unique_ptr<int[]>& ptr; std::size_t index; int& operator*() const { return ptr[index]; } Iterator& operator++() { index++; return *this; } bool operator!=(const Iterator& other) const { return index != other.index; } }; Iterator begin() { return {arr_ptr, 0}; } Iterator end() { return {arr_ptr, ArraySize}; } }; int main() { auto ptr = std::make_unique<int[]>(5); const auto in = std::array{1, 2, 3, 4, 5}; UniqueArrayRange<5> out{ptr}; std::ranges::transform(in, out.begin(), [](const int x) { return x * 2; }); }
包装器内部完全依赖unique_ptr的成员操作,不涉及任何裸指针操作。
方案3:结合std::ranges::subrange与自定义迭代器
复用标准库的subrange,只需要实现一个基于operator[]的迭代器,同样无需裸指针:
#include <ranges> #include <memory> #include <algorithm> #include <iterator> template<typename T> struct UniqueArrayIter { std::unique_ptr<T[]>& ptr; std::size_t pos; T& operator*() const { return ptr[pos]; } UniqueArrayIter& operator++() { pos++; return *this; } bool operator==(const UniqueArrayIter& other) const = default; }; // 特化迭代器特性,适配标准库要求 template<typename T> struct std::iterator_traits<UniqueArrayIter<T>> { using value_type = T; using reference = T&; using iterator_category = std::forward_iterator_tag; }; int main() { auto ptr = std::make_unique<int[]>(5); const auto in = std::array{1, 2, 3, 4, 5}; auto out = std::ranges::subrange( UniqueArrayIter<int>{ptr, 0}, UniqueArrayIter<int>{ptr, 5} ); std::ranges::transform(in, out.begin(), [](const int x) { return x * 2; }); }
内容的提问来源于stack exchange,提问作者digito_evo
相关产品推荐
相关产品推荐

