c ++ push_back复制对象而不是引用

时间:2016-02-08 07:33:21

标签: c++ pointers vector shared-ptr

我在解决下面评论中提到的问题时遇到了一些问题:

class Node {
    public:
        Node(int value): value(value), neighbors() {}
        int value;
        std::vector<std::shared_ptr<Node>> neighbors;
};

    std::vector<Node> nodes;
    nodes.reserve(50);
    for(int j = 0 ; j < 50; ++j) {
        nodes.push_back(Node(j));
    }
    for(int j = 1 ; j < 25; ++j) {
        nodes.at(0).neighbors.push_back(std::make_shared<Node>(nodes.at(j)));
    }

    //The following line is copying nodes.at(0) instead of just 
    //copying a reference to nodes.at(0). Why?
    nodes.at(15).neighbors.push_back(std::make_shared<Node>(nodes.at(0)));

    for(int j = 25 ; j < 50; ++j) {
        nodes.at(0).neighbors.push_back(std::make_shared<Node>(nodes.at(j)));
    }

    std::cout << nodes.at(15).neighbors.at(0).neighbors.size();
    //Prints out 24

    std::cout << nodes.at(0).neighbors.size();
    //Prints out 49

为什么以下行复制nodes.at(0)(返回对节点矢量的第一个元素的引用)而不是存储对它的引用?

    nodes.at(15).neighbors.push_back(std::make_shared<Node>(nodes.at(0)));

3 个答案:

答案 0 :(得分:2)

您的代码中没有任何内容存储引用。您的代码复制节点是因为您在std::make_shared中分配了一个新节点并调用了复制构造函数。

  std::vector<Node> nodes;

它的功能是本地的。保持指针(共享或不共享)或引用此向量的元素是不可能的。也许您想要使用共享指针向量:

 std::vector<std::shared_ptr<Node>> nodes;

请记住,shared_ptr在存在循环引用的情况下不能很好地工作。如果您的数据结构是一般图形,那么shared_ptr可能不适合存储邻居。您可能需要考虑weak_ptr(您必须分别保留所有节点的共享指针容器)。

答案 1 :(得分:1)

Vector始终存储副本。您可以在这里找到更多信息 : Is std::vector copying the objects with a push_back?

答案 2 :(得分:0)

// The following line is copying nodes.at(0) instead of just 
nodes.at(15).neighbors.push_back(std::shared_ptr<Node>(&nodes.at(0))); 

// Notice I didn't call make_shared, because make_shared woul allocate anew Node,
// but you already have allocated your node in your nodes vector (which is global).

// 24 as expected
std::cout << nodes.at(0).neighbors.size() << std::endl;
// 24 as well
std::cout << nodes.at(15).neighbors.at(0)->neighbors.size() << std::endl;

//Insert another element
nodes.at(0).neighbors.push_back(std::make_shared<Node>(nodes.at(30)));

// 25 as expected
std::cout << nodes.at(0).neighbors.size() << std::endl;
// 25 as well
std::cout << nodes.at(15).neighbors.at(0)->neighbors.size() << std::endl;

如果我理解你的问题,请告诉我。

您可以使用std::vector<std::shared_ptr<Node>>,然后按

nodes.at(15).neighbors.push_back(nodes.at(0));

使用共享ptr向量的另一个解决方案是:

std::vector<std::shared_ptr<Node>> nodes;
nodes.reserve(50);

for (int j = 0; j < 50; ++j)
    nodes.push_back(std::make_shared<Node>(j));

for (int j = 1; j < 25; ++j)
    nodes.at(0)->neighbors.push_back(nodes.at(j));

nodes.at(15)->neighbors.push_back(nodes.at(0));

// 24 as expected
std::cout << nodes.at(0)->neighbors.size() << std::endl;
// 24 as well
std::cout << nodes.at(15)->neighbors.at(0)->neighbors.size() << std::endl;

//Insert another element
nodes.at(0)->neighbors.push_back(nodes.at(30));

// 25 as expected
std::cout << nodes.at(0)->neighbors.size() << std::endl;
// 25 as well
std::cout << nodes.at(15)->neighbors.at(0)->neighbors.size() << std::endl;