【问题标题】:C++ range based for loop gives SIGABRT while normal loop works fine基于 C++ 范围的 for 循环提供 SIGABRT,而普通循环工作正常
【发布时间】:2017-01-03 01:27:18
【问题描述】:

这段代码运行良好:

for (int i = 0; i < grid.size(); i++)
    painter.drawRect(grid[i].rect);

此代码不起作用:

for (Square square : grid)
    painter.drawRect(square.rect);

运行时打印失败:

在抛出 'std::bad_alloc' 的实例后调用终止 what(): std::bad_alloc 程序意外结束。

这是调用堆栈:

1  raise
0x7ffff53cf91f 
2  abort
0x7ffff53d151a 
3  __gnu_cxx::__verbose_terminate_handler()
0x7ffff5f3f52d 
4  ??
0x7ffff5f3d2d6 
5  std::terminate()
0x7ffff5f3d321 
6  __cxa_throw
0x7ffff5f3d539 
7  operator new(unsigned long)
0x7ffff5f3dafc 
8  __gnu_cxx::new_allocator<Square>::allocate
new_allocator.h 104 0x408548       
9  std::allocator_traits<std::allocator<Square>>::allocate
alloc_traits.h  416 0x408308       
10 std::_Vector_base<Square, std::allocator<Square>>::_M_allocate
stl_vector.h    170 0x407f54       
11 std::_Vector_base<Square, std::allocator<Square>>::_M_create_storage
stl_vector.h    185 0x407b99       
12 std::_Vector_base<Square, std::allocator<Square>>::_Vector_base stl_vector.h    136 0x4078f3       
13 std::vector<Square>::vector
stl_vector.h    322 0x4075c3       
14 Square::Square
square.h        19  0x407406       
15 Canvas::Canvas
canvas.cpp      23  0x406752       
16 MainWindow::MainWindow
mainwindow.cpp  10  0x4044b6
main.cpp        7   0x404310       

问题发生在canvas.cpp

请说明可能导致此问题的原因。

【问题讨论】:

  • 基于范围的循环会复制每个元素,而基于索引的循环不会。看来Square 的复制成本很高。设为for (Square&amp; square : grid) {...}(注意与号)。
  • 你是对的!谢谢。

标签: c++ qt c++11 for-loop


【解决方案1】:

您尝试的两个循环根本不等效。第一个使用grid[i]vector[] 运算符将reference 返回到向量中的元素,而不是它的副本。第二个版本使用 based-range 来表示:但是您编写它的方式 for(Square square : grid,您要求它为每个元素创建一个 copy 并将其放在变量 square 中。

您的Square 对象似乎是一个重对象,或者它的复制构造函数存在一些问题,导致bad_alloc。但是,由于第一个版本运行良好,要执行等效操作,您需要使 range-based-for 在引用上工作,而不是每个元素的副本:

for (Square& square : grid)  // <-- return a reference on each element.
    painter.drawRect(square.rect);

只要足够对元素执行所需的操作,甚至最好返回 const ref

for (const Square& square : grid) // <-- return a const ref whenever it is enough and the subsequent action does not modify the object
    painter.drawRect(square.rect);

【讨论】:

  • 谢谢先生。 Square确实很重。是时候使用指针了,因为堆栈不会再正常运行了。
  • 您的任何Squares 似乎都没有在堆栈中。它们都存储在std::vector&lt;Square&gt;中,vector将其实际内容放在堆上。
  • @IgorTandetnik 我猜你的评论是针对 OP 的评论,这是真的。亚当这里不是堆栈问题,但无论如何,使用引用将解决问题。很高兴它有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-04
  • 1970-01-01
  • 2016-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-23
相关资源
最近更新 更多