我在理解以下代码的输出时遇到了一些麻烦:
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;
请注意,我不能选择使用类而不是结构。
答案 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类型string
和vector<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)
为什么首先插入节点然后修改向量中的节点?一旦正确构造(完成修改)它就可以插入节点。您根本不需要第一个循环,只需将推送放在第二个循环的末尾