以下不能按预期工作(打印2),因为我猜想,即使向量通过引用传递,节点也会按值传递。我怎么能解决它?
#include <iostream>
using std::cout;
using std::endl;
#include <vector>
using std::vector;
class Node{
public:
int value;
Node(int);
void createChildren(vector<Node> &);
};
//! constructor of a single node
Node::Node(int value)
{
this->value = value;
}
void Node::createChildren(vector<Node> &nodes)
{
for (int i = 0; i < 5; i++) {
Node n(0);
nodes.push_back(n);
if (i == 0) {
value = nodes.size();
}
}
}
int main(void) {
Node a(0);
vector<Node> asdf;
asdf.push_back(a);
asdf[0].createChildren(asdf);
cout << asdf[0].value << endl;
return 0;
}
答案 0 :(得分:2)
执行行nodes.push_back(n);
时,向量会调整大小,使先前保存的引用无效,因为它会将现有成员复制到新分配的内存块。在您的情况下,*this
内的createChildren
就是这样的引用(对于asdf [0])。更改其中的值不再是已定义的行为,因为此对象的析构函数已执行(尝试定义~Node()
并查看何时调用它)
答案 1 :(得分:1)
解决方案与Adrian Regan所说的有些相关。
如果将另一个元素推送到“createChildren()”方法中的节点向量上,则向量需要自行调整大小。当它这样做时,它会将任何现有元素复制到新分配的存储中。
因此,第一次发生这种情况时,它会复制节点0的初始值,其值为0。
编译器将生成一个默认的复制构造函数,它执行按位复制。但是,实现复制构造函数不会有所帮助,因为您将始终丢失节点0的更新值。
小时。
答案 2 :(得分:0)
如果要将Node类放入向量(或任何其他容器),则需要确保它具有复制构造函数和operator = implementation,否则您应该将指针放在向量中的Node中
class Node {
...
public:
Node(const Node& rhs) { ... }
Node& operator=(const Node& rhs) {
if(this == &rhs)
return *this;
value = rhs.value;
// ... other members copied ...
return *this;
}
Node& operator=(Node& rhs) { ... non const version ... }
};
除此之外,你的createChildren()方法应该在循环之后将值设置为5.