【问题标题】:How to add an element into the vector of pointers?如何将元素添加到指针向量中?
【发布时间】:2013-03-12 21:09:03
【问题描述】:

我有这个:

std::vector <BinaryTree*> children;

BinaryTree 是一个类。如何在此向量中添加元素?

我尝试了children.push_back(X),其中X 是该类的一个实例,但它给了我这个错误:

无法将参数 1 从“BinaryTree”转换为“BinaryTree *&&”

【问题讨论】:

    标签: c++ pointers vector


    【解决方案1】:

    只需使用push_back() 并将指针 传递给BinaryTree 的实例:

    std::vector <BinaryTree*> children;
    BinaryTree* pTree = new BinaryTree();
    children.push_back(pTree);
    ...
    delete pTree;
    

    为了避免手动内存管理,如果需要引用语义,请使用智能指针而不是原始指针:

    #include <memory> // For std::shared_ptr
    
    std::vector <std::shared_ptr<BinaryTree>> children;
    std::shared_ptr<BinaryTree> pTree = std::make_shared<BinaryTree>();
    children.push_back(pTree);
    ...
    // No need to delete pTree
    

    std::shared_ptr&lt;&gt; 类模板是 C++11 标准库的一部分。在 C++03 中,您可以使用(几乎)等价的 boost::shared_ptr&lt;&gt;

    #include <boost/shared_ptr.hpp> // For std::shared_ptr
    
    std::vector <boost::shared_ptr<BinaryTree>> children;
    boost::shared_ptr<BinaryTree> pTree = boost::make_shared<BinaryTree>();
    children.push_back(pTree);
    ...
    // No need to delete pTree
    

    最后,如果您根本不需要引用语义并希望将二叉树视为值,您甚至可以考虑定义一个std::vector&lt;BinaryTree&gt;

    std::vector<BinaryTree> children;
    BinaryTree tree;
    children.push_back(tree);
    

    【讨论】:

    • 值得注意的是std::shared_ptr是C++11的特性。
    • @LihO 不是真的,shared_ptr 在 C++03 下可用 std::tr1::shared_ptr
    【解决方案2】:

    从模板参数中省略星号*

    std::vector<BinaryTree> children;
    

    您希望孩子保存数据,而不像 new BinaryTree 那样手动/动态分配内存。

    【讨论】:

    • 绝对不想这样做。正确的做法是将指针保存在容器中。
    • @Cthulhu,感谢您的编辑,我写了“asterix”多年。正如维基百科所说:“不要与 Asterix 混淆。” :-)
    • @arrows template &lt;class T&gt; struct BinaryTree { T value; BinaryTree *left, *right; }?
    • @juanchopanza 当你真正实现它时不会再有趣了,试试吧。
    • @arrows 我们对BinaryTree一无所知,只能猜测这个向量的作用。
    【解决方案3】:

    这实际上取决于谁应该拥有指针。在最简单的情况下,如果向量不拥有它们,那么您将传递 BinaryTree 对象的地址。

    BinaryTree b = ...;
    children.push_back(&b);
    

    但你必须确保b 的寿命至少与children 一样长。

    如果向量拥有指针,那么您可能应该存储智能指针以避免不得不处理内存管理:

    std::vector<std::unique_ptr<BinaryTree>> children;
    children.push_back(std::unique_ptr<BinaryTree>(new BinaryTree(args)));
    

    如果您不知道所有这些“所有权”业务的含义,那么您很可能最好使用一个简单的对象向量:

    std::vector<BinaryTree> children;
    

    【讨论】:

      【解决方案4】:
      std::vector<SomeObject*> objectVector;
      objectVector.push_back(new SomeObject());
      

      我是怎么做的。

      【讨论】:

        【解决方案5】:
        children.push_back(&X);
        

        这将起作用,但请记住,一旦您的对象离开作用域,它的删除器将被调用,您将得到一个无效的指针。

        【讨论】:

          【解决方案6】:
          children.push_back(&X);
          

          像使用指针一样传递地址。但问题是如果该实例超出范围,那么最好这样做

          BinaryTree* X = new BinaryTree;
          children.push_back(X);
          

          这将确保 X 永远不会超出范围,但是您必须在完成后手动删除它。

          【讨论】:

            【解决方案7】:

            vector 包含 指向 BinaryTree 类型对象的指针。你需要

            BinaryTree bt;
            children.push_back( &bt );
            

            但您必须确保bt 对象的生命周期至少与vector 的生命周期相匹配。

            你可能想要这个

            children.push_back( new BinaryTree );
            

            但在这种情况下,您必须在 vector 中包含的指针上调用 delete 以防止内存泄漏。

            显然,这两种选择都不容易管理。一个简单的更改是让您的容器按值存储元素。

            std::vector<BinaryTree> children;
            BinaryTree bt;
            children.push_back( bt );
            

            如果您必须存储指针,请改用智能指针来保存它们。

            std::vector<std::unique_ptr<BinaryTree>> children;
            children.push_back( new BinaryTree );
            

            现在您无需担心在清空向量之前删除对象。

            【讨论】:

              【解决方案8】:

              你有指针向量:

              std::vector <BinaryTree*> children;
              

              所以添加元素的正确方法是:

              BinaryTree* child = new BinaryTree();
              children.push_back(child);
              

              在做这样的事情时要小心:

              {
                  BinaryTree child;
                  children.push_back(&child);
              }
              

              因为此类元素的生命周期可能比向量的生命周期短,并且您最终可能会尝试访问不再存在的元素(悬空指针),从而产生未定义的行为。完成后不要忘记delete这些元素。

              但最好先考虑使用对象向量(即std::vector&lt;BinaryTree&gt;),因为这样可以为您解决丑陋的内存管理问题。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2011-03-12
                • 1970-01-01
                • 2015-09-09
                • 2019-05-15
                • 2013-05-08
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多