临时对象基于范围为 [英] temporary object in range-based for

查看:80
本文介绍了临时对象基于范围为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道一般来说,基于范围的循环中的一个临时的生命周期被扩展到整个循环(我已经读过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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆