c++ - list::iterator 对移至列表无效?
问题描述
我已经使用了相当数量的 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>>();
}
这输出
___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
即指向被移动的list
s 端的迭代器不指向被移动的list
s 端。但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>>();
}
请注意,比较来自两个不同容器的迭代器是未定义的行为,因此最终pos == l.begin()
是未定义的行为,并且 Visual Studio 的调试版本至少会在运行此代码时抛出断言。
我想您的原始代码可以工作,因为std::vector
end
迭代器通常只是实现为指向最后一个元素之后的一个。我会想象std::list
结束迭代器包含一个空指针和一个指向列表的指针。
推荐阅读
- javascript - 如何从异步等待函数而不是 Promise 返回布尔值
(打字稿|反应) - html - 从前端下载图像标签不起作用
- python - 尝试为 peewee 使用自定义 UUID mixin 不会覆盖基本 AutoField ID
- javascript - JS:不能对将被最小化或置于后台的页面使用异步剪贴板 API
- python - pyinstaller 不带包
- python - 直接从子进程输出解析 json 输出
- swift - 如何将对象数据类型上传到 Firestore 中的文档?
- c# - Visual Studio Form 上的错误“对象引用未设置为实例等”
- java - 有谁知道按下 X 时如何关闭对话框窗口?
- java - AWS ElasticSearch:如何将策略应用于索引