【问题标题】:Scope of Stack Allocated Class in a Vector [duplicate]向量中堆栈分配类的范围[重复]
【发布时间】:2015-12-01 13:51:04
【问题描述】:

我的课程安排如下:

#include <iostream>
#include <vector>

struct Tracker
{
    int a = 0;

    void update()
    {
       a++;
    }
};

struct OtherClass
{
    std::vector<Tracker> activeTrack;

    void updateAll()
    {
       for (Tracker tr : activeTrack) {
           tr.update();
       }
    }
};

int main()
{
    OtherClass o;
    o.activeTrack.resize(1);
    o.updateAll();  // does nothing?!

    std::cout << o.activeTrack[0].a << '\n';  // Is 0; should be 1!
}

(live demo)

对于堆栈分配的对象在向量中的行为方式,是否有一些非常简单但我不理解的东西?

【问题讨论】:

  • 请花一些话来解释你真正打算做什么。后续的编辑也偏离了原代码sn-p。
  • @g24l:有吗?该代码是 OP 代码的等效 版本,但采用完整的最小测试用例形式(我们要求)。以前有一些难以阅读的杂乱无章的宣传,这不是必需的,因为问题在代码 cmets 中已明确说明。您对编辑的哪一部分感到困惑?
  • @LightnessRacesinOrbit 与之前的版本相比非常清楚,您发现“漫无边际的宣传”是哪一部分?该操作还提到了 Tracker 在内部共享 ptr。可能会更好地反映在那个版本中。将问题定制为答案并不是一个好习惯。
  • @g24l:我没有“根据答案定制问题”。我针对 Stack Overflow 定制了这个问题。 OP 只提到了一个 shared_ptr 作为一个有趣的观察在问题已经解决之后。无需再次将其恢复。请... 停止 ...
  • @LightnessRacesinOrbit 在我看来并不像,共享的 ptr 在 Tracker object 中,可以通过指针复制它并更新值。最好有原始代码。无论如何,您添加的测试用例非常明显。

标签: c++ c++11


【解决方案1】:
for (Tracker tr : activeTrack) {
   tr.update();
}

在这里您每次都制作一个副本,并在副本上执行update()

使用参考

for (Tracker& tr : activeTrack) {
   tr.update();
}

【讨论】:

  • @Lightness Races in Orbit 所做的编辑很好地表达了我遇到的问题(没有正确理解 C++ 语义)。
  • 它不会影响问题的问题,但是知道正在调用复制构造函数有助于我理解为什么更新由 shared_ptr 指向的对象仍然有效,但不是更新诠释。
  • @AdnanEK 他说的是跟踪器对象而不是 activeTrack 上的共享 ptr,这可以区分问题。因此,如果在向量中具有跟踪器对象的共享 ptr 副本,则 for 循环将起作用。
  • @g24l:我认为 OP 比你更有资格知道他自己在想什么。请不要再试图迷惑人们好吗?问题已经解决了。这个问题结束了。没有必要继续困惑。谢谢。
  • @LightnessRacesinOrbit 当然,但如果可以的话,最好在上下文中回复。他说 Tracker 内部有一个共享指针,您可以将其编辑为整数类型。就在你的帖子之后。
【解决方案2】:

您的迭代器有问题,而且您没有创建要添加到向量的跟踪器实例,这个可以工作。

#include <iostream>
#include <vector>
using namespace std;
struct Tracker
{
    int a = 0;

    void update()
    {
       a++;
    }
};

struct OtherClass
{
    std::vector<Tracker> activeTrack;

    void updateAll()
    {
       for (vector <Tracker>::iterator it = activeTrack.begin(), end=activeTrack.end(); it != end; ++it)
       it->update();
    }
};

int main()
{
    OtherClass o;
    o.activeTrack.resize(1);
    Tracker T;
    o.activeTrack.push_back(T);
    o.updateAll();  
    std::cout << o.activeTrack[0].a << '\n'; 

 }

希望对你有帮助

【讨论】:

  • 你为什么要删除简洁的 C++11 for 循环并用一个丑陋的过时的等价物替换它?
  • 这没什么不好。它有助于减少编译时间。
【解决方案3】:

Vector 默认在内部总是在堆上分配。为此,它会复制传递给它的内容。问题在于您每次都复制值的基于范围的 for 循环。

相反,您可以使用 auto 来获取迭代器

for( auto it = activeTrack.begin() ; it != activeTrack.end() ; ++it)
{
  it->update();
}

这样就不用担心路过问题了。

【讨论】:

  • 为什么要在这里使用迭代器?您无缘无故地放弃了 range-for 的全部好处。
  • “Vector 内部总是在堆上分配” 这也是错误的。分配器是可配置的。
  • @LightnessRacesinOrbit 为真,除非指定了分配器并且它确实在堆栈上分配。那里有太多的如果。为了让你开心,我会稍作修改。
  • 对,所以你的答案在这个意义上是正确的,只要“总是”意味着“不总是”。
  • @LightnessRacesinOrbit “-always” 是依赖于“默认”的实现。
猜你喜欢
  • 2014-08-12
  • 2011-12-01
  • 2018-02-15
  • 2019-11-26
  • 1970-01-01
  • 2012-07-19
  • 1970-01-01
  • 2014-10-16
  • 1970-01-01
相关资源
最近更新 更多