结构是“重置”

时间:2011-11-11 14:17:43

标签: c++ vector struct

我在理解以下代码的输出时遇到了一些麻烦:

int main(void)
{
    vector<TreeNode> tree;
    for(int i = 0; i < 50; i++)
    {
        TreeNode node;
        tree.push_back(node);
    }

    for(int i = 0; i < 50; i++)
    {
        Image image;
        image.Path = "TestPath";
        image.Votes = 0;

        TreeNode node = tree.at(i);
        node.images.push_back(image);
        node.images.push_back(image);
    }

    TreeNode node = tree.at(0);
    cout << "TEST" << endl;
    cout << node.images.size() << endl;
}

输出:

TEST
0

为什么输出0以及我该怎么做才能修复它?我希望大小为2而不是0。 它可能与结构的工作方式有关。我的两个定义结构如下:

typedef struct
{
    string Path;
    int Votes;
} Image;

typedef struct
{
    int treeIndex;
    float centroid;
    vector<float*> features;
    vector<Image> images;
} TreeNode;

请注意,我不能选择使用类而不是结构。

6 个答案:

答案 0 :(得分:9)

vector :: at返回对象的引用。

你的行

TreeNode node = tree.at(i);

正在节点中创建TreeNode的副本,因此当您向其添加图像时,它会将它们添加到不在向量中的新对象。

如果您改为使用

TreeNode& node = tree.at(i);

它会正确添加图像。

答案 1 :(得分:3)

您正在按值检索节点,并修改本地副本。尝试

TreeNode &node = tree.at(i);

答案 2 :(得分:2)

你的问题在这一行:

TreeNode node = tree.at(i);

您在此处创建存储在容器中的节点的副本。您的后续代码会修改该副本,而不是原始副本。最后,您可以从容器中访问未修改的原件。

相反,请使用

TreeNode& node = tree.at(i);

使node引用存储在向量中的对象。 &表示节点no不是TreeNode对象,而是对TreeNode对象的引用。也就是说,对node的每次访问都会实际访问绑定的对象,即tree.at(i)返回的对象。

顺便说一句,关于你的代码还有其他注意事项。

首先,你说你不能使用类,但必须使用结构。在C ++中,struct和class完全相同,只是结构默认情况下所有成员都是公共的。也就是说,以下两个代码示例完全等效:

struct X
{
  int i;
  int k;
};

class X
{
public:
  int i;
  int k;
};

实际上,您甚至可以使用struct向前声明您的类型,然后使用class进行定义,反之亦然。

使用struct代替class的需要只能表示以下两种情况之一:您需要将文件也包含在C中(不知道class关键字) ,但在你的情况下你不能这样做,因为C既不知道矢量也不知道字符串。或者你需要让你的类成为POD(普通旧数据)类型,但你的结构也不是POD tyoes,因为它们有非POD类型stringvector<T>的成员。换句话说,你的结构已经是类,无论从哪个方面来说都是类。

在相关节点中,由于您无法在C中包含结构的定义,因此在此处使用typedef是没有意义的。在C ++中,

struct Image
{
  string Path;
  int Votes;
};

已经允许您使用Image引用类型(与C中不同,在这种情况下您需要使用struct Image来引用类型)。

答案 3 :(得分:1)

TreeNode node = tree.at(i);

您将获得节点的副本并修改副本,而原始文件保持不变。

答案 4 :(得分:1)

TreeNode node = tree.at(i);
node.images.push_back(image);
node.images.push_back(image);

您已经在索引TreeNode处获取了i副本,并添加了内容。然后在副本离开范围时立即销毁该副本。

相反,请参考以便您从容器中处理原始对象:

TreeNode& node = tree.at(i);
node.images.push_back(image);
node.images.push_back(image);

答案 5 :(得分:0)

为什么首先插入节点然后修改向量中的节点?一旦正确构造(完成修改)它就可以插入节点。您根本不需要第一个循环,只需将推送放在第二个循环的末尾