我有一个像这样的代码:
std::vector<int> v1 = { 1, 2, 3, 4 };
std::vector<int> v2 = { 7, 8, 9, 10 };
std::vector<int>::iterator it = std::next(v1.begin());
v1 = v2;
int test = *it;
std::cout << test;
上面的代码会抛出一个错误:迭代器不能解除引用。
但是,如果我用列表替换vector如下:
std::list<int> v1 = { 1, 2, 3, 4 };
std::list<int> v2 = { 7, 8, 9, 10 };
std::list<int>::iterator it = std::next(v1.begin());
v1 = v2;
int test = *it;
std::cout << test;
代码只是按预期运行而没有错误 从Iterator invalidation rules和std::list::operator=开始,在调用operator =后,我被告知,除了最终迭代器之外,与此容器相关的所有迭代器,引用和指针都无效。但为什么上面的代码与std :: list有效?我误解了一些必要的东西吗?
答案 0 :(得分:4)
当迭代器失效时,取消引用它是未定义的行为。因此,就规范而言,无论你采取何种行为都是无关紧要的。 &#34;根据您的期望,工作&#34;是允许的行为之一。
FWIW(不多,tbh),我希望std::list
赋值运算符的实现等同于:
list& operator=(list const& rhs) {
if (this == &rhs)
return *this;
auto lhs_i = begin();
auto rhs_i = rhs.begin();
// write over the elements in any currently existing nodes, this
// avoids any unnecessary allocations
while (lhs_i != end() && rhs_i != rhs.end()) {
*lhs_i++ = *rhs_i++;
}
// erase any extra elements if size() > rhs.size()
erase(lhs_i, end());
// push back additional elements if size() < rhs.size()
while (rhs_i != rhs.end()) {
push_back(*rhs_i++);
}
return *this;
}
如果是,你可以看到,对于像你这样的情况,列表都有相同数量的元素,没有创建或销毁任何元素,所以你非常希望迭代器继续工作完全正常。当然,这完全是猜测,绝对不是你应该依赖的行为,因为即使是实施的情况,他们也可以在下一个版本中更改它而不另行通知。
答案 1 :(得分:1)
这是未定义的行为,但GCC有调试容器来捕获这种行为。
使用Attempt to reload List/Util.pm aborted.
Compilation failed in require at /home/travis/perl5/perlbrew/perls/5.22.0/lib/site_perl/5.22.0/Sub/Exporter/Progressive.pm line 9.
BEGIN failed--compilation aborted at /home/travis/perl5/perlbrew/perls/5.22.0/lib/site_perl/5.22.0/Sub/Exporter/Progressive.pm line 9.
Compilation failed in require at /home/travis/perl5/perlbrew/perls/5.22.0/lib/site_perl/5.22.0/Devel/GlobalDestruction.pm line 11.
BEGIN failed--compilation aborted at /home/travis/perl5/perlbrew/perls/5.22.0/lib/site_perl/5.22.0/Devel/GlobalDestruction.pm line 11.
Compilation failed in require at /home/travis/perl5/perlbrew/perls/5.22.0/lib/site_perl/5.22.0/Moo/_Utils.pm line 21.
BEGIN failed--compilation aborted at /home/travis/perl5/perlbrew/perls/5.22.0/lib/site_perl/5.22.0/Moo/_Utils.pm line 21.
Compilation failed in require at /home/travis/perl5/perlbrew/perls/5.22.0/lib/site_perl/5.22.0/Moo.pm line 4.
BEGIN failed--compilation aborted at /home/travis/perl5/perlbrew/perls/5.22.0/lib/site_perl/5.22.0/Moo.pm line 4.
Compilation failed in require at /home/travis/build/xtaran/CGI-Github-Webhook/build_dir/lib/CGI/Github/Webhook.pm line 11.
BEGIN failed--compilation aborted at /home/travis/build/xtaran/CGI-Github-Webhook/build_dir/lib/CGI/Github/Webhook.pm line 11.
Compilation failed in require at ./cgitest.pl line 10.
BEGIN failed--compilation aborted at ./cgitest.pl line 10.
script /cgi-bin/cgitest.pl generated no valid headers at /home/travis/perl5/perlbrew/perls/5.22.0/lib/site_perl/5.22.0/CGI/Test.pm line 468.
Use of uninitialized value $in_fname in unlink at /home/travis/perl5/perlbrew/perls/5.22.0/lib/site_perl/5.22.0/CGI/Test.pm line 469.
Use of uninitialized value $in_fname in concatenation (.) or string at /home/travis/perl5/perlbrew/perls/5.22.0/lib/site_perl/5.22.0/CGI/Test.pm line 469.
can't unlink : No such file or directory at /home/travis/perl5/perlbrew/perls/5.22.0/lib/site_perl/5.22.0/CGI/Test.pm line 469.
:
-D_GLIBCXX_DEBUG