C ++ векторные элементы копирования? - PullRequest
4 голосов
/ 24 июля 2010

Я хотел бы использовать динамический массив в C ++ (что-то вроде ArrayList или Vector в Java.)
В этом примере копируются объекты t1, t2 ... или в адрес добавляется только его адрес.vector?
Нужно ли реализовывать конструктор копирования для класса 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;
}

Ответы [ 2 ]

4 голосов
/ 24 июля 2010

В вашем примере vector<Node> будет хранить копии ваших узлов, поэтому будут скопированы t1, t2.

Кроме того, конструктор копирования по умолчанию для 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, он не должен ее удалять.

Производительность целесообразна, поскольку ваш узел достаточно недорог для копирования (int иуказатель), хранение копии в порядке.Если ваш класс Node сделал глубокое копирование, то с точки зрения производительности было бы лучше использовать vector<Node*>

2 голосов
/ 24 июля 2010

std::vector и другие контейнеры стандартной библиотеки C ++ имеют семантику значений, иными словами, они ожидают содержать реальные объекты, а не указатели на объекты. Таким образом, всякий раз, когда вы помещаете объект в стандартный контейнер библиотеки, контейнер копирует его. Семантика значений имеет определенные значения, такие как автоматическая очистка при разрушении контейнера, вызывающая утечку памяти, если ваш контейнер содержит указатели на объекты; в этом конкретном случае вам нужно вручную удалить указанные объекты.

Я бы порекомендовал, чтобы, если у вас есть объекты, которые можно копировать дешево или дорого, но копировать не часто, поместите их в контейнер как значение. Если вам требуется, чтобы контейнер содержал полиморфные объекты или часто копируемые, дорогостоящие для копирования объекты, держите их в контейнере либо с помощью boost::shared_ptr<>, либо используйте соответствующий контейнер boost::ptr_xxx, например boost::ptr_vector.

...