基于范围的临时对象

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (11)

在一个范围内的一个临时的生命时间-基础。for循环扩展到整个循环

for (auto &thingy : func_that_returns_eg_a_vector())
  std::cout << thingy;

现在,当我尝试做一些我认为与Qt相似的事情时,我在记忆问题上步履蹒跚。QList集装箱:

#include <iostream>
#include <QList>

int main() {
  for (auto i : QList<int>{} << 1 << 2 << 3)
    std::cout << i << std::endl;
  return 0;
}

这里的问题是valrun显示了在QList上课。但是,修改示例以便将列表存储在变量中提供了正确的结果:

#include <iostream>
#include <QList>

int main() {
  auto things = QList<int>{} << 1 << 2 << 3;
  for (auto i : things)
    std::cout << i << std::endl;
  return 0;
}

如何使用QList,或如何QList落实了吗?

提问于
用户回答回答于

既然你用的是C++11,这将通过瓦莱尔:

int main() {
  for (auto i : QList<int>{1, 2, 3})
    std::cout << i << std::endl;
  return 0;
}
这个问题与基于范围的C++11并不完全相关.。以下代码演示了相同的问题:
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<<)将返回该临时对象。因此,您现在引用已释放内存的内容。

用户回答回答于

编译器不可能知道引用是三个调用的结果operator <<绑定到临时对象。QList<int>{},所以暂时的寿命是不会延长的。编译器不知道(也不能期望它知道)函数的返回值,但它的类型除外。如果它是一个引用,它不知道它可能绑定到什么。为了使延长寿命的规则适用,绑定必须是直接的。

这应该有效,因为列表不再是临时的:

#include <iostream>
#include <QList>

int main() {
  auto things = QList<int>{};
  for (auto i : things << 1 << 2 << 3)
    std::cout << i << std::endl;
  return 0;
}

这应该是有效的,因为绑定是直接的,所以规则可以适用:

#include <iostream>
#include <QList>

int main() {
  for (auto i : QList<int>{1, 2, 3})
    std::cout << i << std::endl;
  return 0;
}

扫码关注云+社区