临时对象基于范围为 [英] temporary object in range-based for
问题描述
我知道一般来说,基于范围的循环中的一个临时的生命周期被扩展到整个循环(我已经读过C++11:语句的基于范围:range-init生命周期?)。因此,这样的东西一般是这样的:
I know that in general the life time of a temporary in a range-based for
loop is extended to the whole loop (I've read C++11: The range-based for statement: "range-init" lifetime?). Therefore doing stuff like this is generally OK:
for (auto &thingy : func_that_returns_eg_a_vector())
std::cout << thingy;
现在,当我尝试做某些我认为与Qt类似的事情时, QList
容器:
Now I'm stumbling about memory issues when I try to do something I thought to be similar with Qt's QList
container:
#include <iostream>
#include <QList>
int main() {
for (auto i : QList<int>{} << 1 << 2 << 3)
std::cout << i << std::endl;
return 0;
}
这里的问题是valgrind显示无效的内存访问 QList
类。然而,修改示例以使列表存储在变量中提供了正确的结果:
The problem here is that valgrind shows invalid memory access somewhere inside the QList
class. However, modifying the example so that the list is stored in variable provides a correct result:
#include <iostream>
#include <QList>
int main() {
auto things = QList<int>{} << 1 << 2 << 3;
for (auto i : things)
std::cout << i << std::endl;
return 0;
}
现在我的问题是:我在第一种情况下做一些事例如未定义的行为(我没有足够的经验阅读C ++标准为了自己回答这个问题)?或者这是一个问题,我如何使用 QList
,或如何实现 QList
?
推荐答案
由于您使用的是C ++ 11,因此您可以使用初始化列表。这将通过valgrind:
Since you're using C++11, you could use initialization list instead. This will pass valgrind:
int main() {
for (auto i : QList<int>{1, 2, 3})
std::cout << i << std::endl;
return 0;
}
涉及基于范围的或甚至C ++ 11。下面的代码演示了同样的问题:
The problem is not totally related to range-based for or even C++11. The following code demonstrates the same problem:
QList<int>& things = QList<int>() << 1;
things.end();
或:
#include <iostream>
struct S {
int* x;
S() { x = NULL; }
~S() { delete x; }
S& foo(int y) {
x = new int(y);
return *this;
}
};
int main() {
S& things = S().foo(2);
std::cout << *things.x << std::endl;
return 0;
}
无效读取是因为表达式 S()
(或 QList< int> {}
)在声明之后被破坏(在C ++ 03和C ++ 11§ 12.2 / 5),因为编译器不知道方法 foo()
(或 operator
The invalid read is because the temporary object from the expression S()
(or QList<int>{}
) is destructed after the declaration (following C++03 and C++11 §12.2/5), because the compiler has no idea that the method foo()
(or operator<<
) will return that temporary object. So you are now refering to content of freed memory.
这篇关于临时对象基于范围为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!