是这种减少的测序调用不确定的行为
Is the sequencing of this decrement invoking undefined behaviour?
我正在寻找确认,澄清是该代码定义是否很好。
通过将迭代器重新分配给容器的erase()
函数的结果,将容器的元素删除在循环中。循环通常有点混乱:
struct peer { int i; peer(int i): i(i) {} };
int main()
{
std::list<peer> peers {0, 1, 2, 3, 4, 5, 6};
for(auto p = peers.begin(); p != peers.end();) // remember not to increment
{
if(p->i > 1 && p->i < 4)
p = peers.erase(p);
else
++p; // remember to increment
}
for(auto&& peer: peers)
std::cout << peer.i << ' ';
std::cout << 'n';
}
输出: 0 1 4 5 6
在我看来,以下情况可能会更加整洁,假设它没有调用不确定的行为:
struct peer { int i; peer(int i): i(i) {} };
int main()
{
std::list<peer> peers {0, 1, 2, 3, 4, 5, 6};
for(auto p = peers.begin(); p != peers.end(); ++p)
if(p->i > 1 && p->i < 4)
--(p = peers.erase(p)); // idiomatic decrement ???
for(auto&& peer: peers)
std::cout << peer.i << ' ';
std::cout << 'n';
}
输出: 0 1 4 5 6
我认为这项工作的原因如下:
peers.erase()
将始终返回增量的p
,因此再次将其降低是安全的peers.erase(p)
使p
的A 复制,因此由于测序参考
,它不会在错误的值上运行p = peers.erase(p)
返回p&
,因此减少在正确的对象引用上运行。
,但我有疑虑的怀疑。我担心通过在同一表达式中使用p
在CC_9中用作参数,尽管它看起来还可以。
任何人都可以在这里看到我的评估问题吗?还是定义得当?
它取决于您用于检测这些元素删除的条件。如果您尝试删除第一个元素,它将失败,因为erase
将返回新的begin()
,然后您将其降低。这是非法的,即使您立即将其再次增加。
为了避免此错误,并且由于它更常见和可读,所以我坚持第一个版本。
第二版是 - 正如@danielfrey所说的 - 错误,但是如果您不喜欢第一个版本,为什么不做这样的事情:
std::list<int> myList = { 0, 1, 2, 3, 4, 5, 6 };
myList.remove_if(
[](int value) -> bool {
return value > 1 && value < 4;
}
);
/* even shorter version
myList.remove_if([](int value) -> bool {
return (value > 1 && value < 4);
});
*/
for(int value : myList) {
std::cout << value << " ";
}
这给出输出:
0 1 4 5 6
实时示例。
相关文章:
- 不确定要在我的main中放入什么才能使我的代码正常工作
- 不确定如何装饰我的C++库代码以在 C 中使用
- C++功能泄漏内存,我是C++新手,不确定如何解决
- C++ 编译器错误:P1LinkedList.cpp:145:错误:重载的"to_string(int&)"调用不明确
- "错误 C0000:语法错误,令牌"<EOF>"处出现意外$end,并且不确定
- 为什么对模板的调用不模棱两可?
- 代码在 CodeSignal 中工作不正确。不确定这是否是我的代码缺陷
- 为什么以下代码是不确定的?
- 编译错误:"lvalue required as left operand of assignment" 不确定原因
- 调用不在基类中的派生类函数而不进行动态强制转换,以最大程度地提高性能
- Tbb 库:错误:编写自定义类函数而不是 lambda 表达式时,对函数的调用不匹配
- 误用指针会产生分段错误。我仍然不确定如何纠正它
- C++协程:调用不带co_await的协程函数
- 如何在C++中停止调用不兼容的方法?
- 调用gluPerspective和gluLookAt给了我一个不确定的参考
- 如果无限循环在C 中仍然不确定的行为,如果它调用共享库
- 是这种减少的测序调用不确定的行为
- OnTimer从未被调用,不确定原因
- 不确定如何使用模板调用类函数
- 为什么我们说虚拟函数的调用不能在编译时确定