我想从 a 中获取一系列元素std::vector<MyClass>
并将它们存储为const
-ref,因为我只想读取它们但不想修改它们。
#include <iostream>
#include <vector>
// A "large" user class
class MyClass
{
public:
int data;
MyClass(int val) : data(val) {}
};
int main()
{
// Initialize vector to MyClass objects
std::vector<MyClass> myClass{1, 2, 3, 4, 5, 6, 7, 8};
// Get const reference to element with index 0
const auto &el = myClass[0];
// Get const references to a range of elements
const unsigned int start = 1, end = 4;
// const auto &elRange = ???
return 0;
}
我怎样才能在 C++17 或更低版本中实现这样的事情?
2
最佳答案
3
我想从 std::vector 中获取一系列元素并将它们存储为 const 引用,因为我只想读取它们但不想修改它们。
最好的方法是使用,这需要支持。
否则,你可以编写一个简单的SimpleSpan
类来实现这一点。简单如下:
// A simple span-like class for C++17
template<typename T>
class SimpleSpan
{
T* data_;
std::size_t size_;
public:
constexpr SimpleSpan(T* data, std::size_t size) : data_{ data }, size_{ size } {}
constexpr T& operator[](std::size_t index) { return data_[index]; }
constexpr T& operator[](std::size_t index) const { return data_[index]; }
constexpr T* begin() { return data_; }
constexpr T* end() { return data_ + size_; }
constexpr T* begin() const { return data_; }
constexpr T* end() const { return data_ + size_; }
constexpr std::size_t size() const { return size_; }
};
并且只是
// Get const references to a range of elements using our SimpleSpan
const unsigned int start = 1, end = 4;
SimpleSpan<const MyClass> elRange(&myClass[start], end - start);
4
-
我们不必编写此类的析构函数吗?因为
SimpleSpan
有一个原始指针作为成员
– -
2@Mathieu 该类不拥有或管理数据。您会在建议的析构函数中放入什么?
– -
5@Mathieu std::span/ SimpleSpan 是连续对象序列的非拥有视图。它不直接管理任何资源。它设计得简单轻量,避免了自定义资源管理的需要。因此,不需要 3/5 规则!
–
-
3这就是向量上的引用/指针/视图的问题。您不应将它们存储在任何地方(仅在本地范围内使用它们)。对底层向量的一次修改可能会重新分配,然后您的视图将不再有效。
–
|
这就是用途,但您需要 C++20 来实现它。
如果您使用较低的 C++ 版本,则可以使用。 (它需要 2 个标头才能包含在项目中,您不需要整个 boost 库)
auto elements = boost::span<const MyClass>{myClass}.subspan(start, end-start);
|
const auto elRange = std::span(&myClass[1], &myClass[4]);
3
-
3我忘了说了。我只有 c++17
– -
如果您不想使用索引和算术,请编写自己的视图类。
–
-
@Mathieu 然后编辑你的问题并在那里清楚地说明这一点,以便每个人都会注意到这一点。
–
|
–
const_iterator
s:const auto elRangeBegin = myClass.cbegin() + 1; const auto elRangeEnd = myClass.cbegin() + 4;
–
|