我正在創建一個使用unique_ptr
的數據結構。我現在想要在這個數據結構上定義不同的迭代器,但是我的數據結構的節點是數據本身的一部分。正因爲如此,我希望迭代器返回實際節點,而不僅僅返回其中包含的值。使用unique_ptr實現的列表的迭代器
這是我走到這一步,(更加簡化的例子):
#include <algorithm>
#include <iostream>
#include <memory>
using namespace std;
template <typename T> struct node {
node(T val) : val(val), next(nullptr) {}
node(T val, unique_ptr<node<T>> &n) : val(val), next(move(n)) {}
T val;
unique_ptr<node<T>> next;
template <bool Const = true> struct iter {
using reference =
typename std::conditional<Const, const node<T> *, node<T> *>::type;
iter() : nptr(nullptr) {}
iter(node<T> *n) : nptr(n) {}
reference operator*() { return nptr; }
iter &operator++() {
nptr = nptr->next.get();
return *this;
}
friend bool operator==(const iter &lhs, const iter &rhs) {
return lhs.nptr == rhs.nptr;
}
friend bool operator!=(const iter &lhs, const iter &rhs) {
return lhs.nptr != rhs.nptr;
}
node<T> *nptr;
};
iter<> begin() const { return iter<>(this); }
iter<> end() const { return iter<>(); }
iter<false> begin() { return iter<false>(this); }
iter<false> end() { return iter<false>(); }
};
template <typename T> void pretty_print(const unique_ptr<node<T>> &l) {
auto it = l->begin();
while (it != l->end()) {
auto elem = *it;
cout << elem->val << endl;
++it;
}
}
int main() {
auto a = make_unique<node<int>>(4);
auto b = make_unique<node<int>>(3, a);
auto c = make_unique<node<int>>(2, b);
auto d = make_unique<node<int>>(1, c);
for (auto *elem : *d) {
elem->val = elem->val - 1;
}
pretty_print(d);
return 0;
}
是它認爲不好的做法,暴露原始指針的數據結構的這樣的元素呢?這會在更復雜的例子中起作用,特別是在const
-正確性方面?
'std :: vector'也維護其元素的唯一所有權,但是每次使用'operator []'或iterate時,都會獲得對它們的引用。 [非擁有指針和引用罰款](https://www.youtube.com/watch?v=xnqTKD8uD64#t=14m48s) –
沒有任何錯誤通過非擁有指針作爲原始指針。標準庫,即使添加了'std :: observer_ptr',它基本上是一個n對象中的原始指針。傳遞周圍唯一指針的引用非常糟糕。通過引用它的內容。 –
@瑞安海寧:好點。我明確表示這也是一個合理的選擇。 – ShadowRanger