C++向量复制元素?

4
我想在C++中使用动态数组(类似于Java中的ArrayList或Vector)。
在这个例子中,t1, t2等对象是被复制还是仅添加了它们的地址到向量中?
我需要为Node类实现一个拷贝构造函数吗?还是默认构造函数会生成一个“适当”的副本(因为类中有指针)?
或者我只需声明一个vector<Node*>以避免复制?
并且我是否需要实现一个析构函数来删除other_node指针,或者它可以被程序使用并仍然存储在vector中?
#include <vector>

using namespace std;

class Node {
public:
    int id;
    Node* other_node;
};

int main(int argc, char** argv) {
    vector<Node> nodes;
    Node t1;
    t1.id = 0;
    t1.other_node = NULL;
    Node t2;
    t2.id = 1;
    t2.other_node = &t1;
    Node t3;
    t3.id = 2;
    t3.other_node = &t2;
    Node t4;
    t4.id = 3;
    t4.other_node = &t1;
    nodes.push_back(t1);
    nodes.push_back(t2);
    nodes.push_back(t3);
    nodes.push_back(t4);
    for (vector<Node>::iterator it = nodes.begin(); it != nodes.end(); it++) {
        if (it->other_node) {
            printf("%d (other.id: %d)\n", it->id, it->other_node->id);
        } else {
            printf("%d (other.id: NULL)\n", it->id);
        }
    }
    getchar();
    return 0;
}

1
只是一个小建议,因为你使用了 std::vector,所以最好使用 std::cout - Alan
2个回答

4
在你的例子中,vector<Node> 将会存储节点的副本,因此 t1t2 会被复制。此外,Node 的默认拷贝构造函数会进行"浅拷贝"。
Node* head = new Node();
Node* next = new Node();
head->other_node = next;
Node* other_head = new Node(*head);
*(other_head->other_node)*(head->other_node)是同一个节点。你需要决定是否希望这种行为。
关于析构函数:你应该只删除/释放类实例分配的内存,除非你有充分的理由来占有这段内存。对于你的列表,一般情况下,由other_node指向的内存不是由你的列表分配的,因此不应该删除它。
就性能而言,由于Node的复制成本相对较低(一个int和一个指针),因此存储副本是可以接受的。如果你的Node类进行了深拷贝,那么从性能的角度来看,最好使用vector<Node*>

2

std::vector和其他C++标准库容器具有值语义,也就是说它们期望保存实际的对象而不是对象指针。因此,每当您将一个对象放入标准库容器中时,容器都会复制它。值语义有一些含义,比如在容器销毁时自动清理可能会导致内存泄漏,如果您的容器保存了对象指针;在这种特殊情况下,您需要手动删除指向的对象。

我的建议是,如果您有便宜或不经常复制的对象,请将它们作为值放入容器中。如果您需要容器保存多态对象或者需要频繁复制、昂贵的对象,请使用boost::shared_ptr<>或者使用适当的boost::ptr_xxx容器,例如boost::ptr_vector


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接