Shi*_*ari 0 c++ iterator list move-semantics
我已经使用了相当数量的 C++,但没有那么多std::list.. 在我当前的项目中,我需要一个std::list<..>数据成员,以及跟踪列表中带有std::list<..>::iterator. 该对象也必须是可移动的,但在我的情况下,默认的移动构造函数是不可能的。这里std::list做了一些让我感到惊讶的事情。
考虑
#include <list>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
template<typename T>
void test() {
T l { 1, 2, 3, 4, 5 };
cout << "l = "; for(const auto& e: l) cout << e << " "; cout << endl;
auto pos = find(l.begin(), l.end(), 6);
if (pos == l.end()) cout << "l end\n";
cout << "---- moving l > lmv ----" << endl;
T lmv { std::move(l) };
cout << "l = "; for(const auto& e: l) cout << e << " "; cout << endl;
cout << "lmv = "; for(const auto& e: lmv) cout << e << " "; cout << endl;
if (pos == l.end()) cout << "l end\n";
if (pos == lmv.end()) cout << "lmv end\n";
}
int main() {
cout << "___vector___\n";
test<vector<int>>();
cout << "___list___\n";
test<list<int>>();
}
Run Code Online (Sandbox Code Playgroud)
这输出
___vector___
l = 1 2 3 4 5
l end
---- moving l > lmv ----
l =
lmv = 1 2 3 4 5
lmv end
___list___
l = 1 2 3 4 5
l end
---- moving l > lmv ----
l =
lmv = 1 2 3 4 5
l end
Run Code Online (Sandbox Code Playgroud)
即指向被移动list的结束的迭代器,不指向被移动list的结束的结束。但它确实 for vector,这是我一直期望的,如果迭代器本质上是指针。为什么list不同?元素的内存位置不应该随着移动而改变..list移动改变列表迭代器吗?为什么?
我在 Windows 10 上的 MSYS2 下使用“g++.exe(Rev1,由 MSYS2 项目构建)10.2.0”
移动容器时应保留迭代器。
然而end,容器的迭代器不指向元素,因此在移动容器时允许无效。
如果您更改您的代码以使用begin而不是end它按您的预期工作。
#include <list>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
template<typename T>
void test() {
T l { 1, 2, 3, 4, 5 };
cout << "l = "; for(const auto& e: l) cout << e << " "; cout << endl;
auto pos = find(l.begin(), l.end(), 1);
if (pos == l.begin()) cout << "l begin\n";
cout << "---- moving l > lmv ----" << endl;
T lmv { std::move(l) };
cout << "l = "; for(const auto& e: l) cout << e << " "; cout << endl;
cout << "lmv = "; for(const auto& e: lmv) cout << e << " "; cout << endl;
if (pos == l.begin()) cout << "l begin\n";
if (pos == lmv.begin()) cout << "lmv begin\n";
}
int main() {
cout << "___vector___\n";
test<vector<int>>();
cout << "___list___\n";
test<list<int>>();
}
Run Code Online (Sandbox Code Playgroud)
请注意,比较来自两个不同容器的迭代器是未定义行为,因此最终pos == l.begin()是未定义行为,Visual Studio 的调试版本至少会在运行此代码时抛出断言。
我想您的原始代码有效,因为std::vector end迭代器通常只是实现为指向最后一个元素之后的一个。我会想象std::list结束迭代器持有一个空指针和一个指向列表的指针。