【问题标题】:return a pointer of vector with shared_ptr返回带有 shared_ptr 的向量指针
【发布时间】:2013-07-03 12:00:09
【问题描述】:

我正在使用 vector 的 shared_ptr 进行测试。目的很简单,我想返回一个vector的指针并访问其中的值。但它给出了例外。 “未处理的异常在.. std:out_of_range 在内存位置..”。我正在使用 Visual Studio 2012。

vector<int>* func()
{
    boost::shared_ptr<vector<int> > vec(new vector<int>());

    vec->push_back(123);
    return vec.get();
    }

int _tmain(int argc, _TCHAR* argv[])
{
    vector<int>* result = func();

    cout << result->at(0); // ERROR here
    return 0;
}

【问题讨论】:

  • 您不是在返回共享指针,而是在返回它包含的向量。共享包装器此时丢失。
  • @not-TonyTheLion 糟糕,糟糕的评论。请不要再写 cmets。
  • 公平地说,大多数人甚至对 C 中的指针概念都感到困惑——更不用说共享指针的魔力了。共享指针是奇妙的神奇事物 - 但不像 Java 引用那么简单,因此您可以理解人们如何(非常)错误地理解它。

标签: c++ visual-c++ boost


【解决方案1】:

如果您想使用共享指针,则返回共享指针,而不是原始指针。否则,当shared_ptr 超出范围时,它将破坏向量。访问该向量将导致未定义的行为。

boost::shared_ptr<vector<int> > func()
{
    boost::shared_ptr<vector<int> > vec(new vector<int>());
    vec->push_back(123);
    return vec;
}

但是,请注意,按值返回向量要好得多:

vector<int> func()
{
    vector<int> vec;
    vec.push_back(123);
    return vec;
}

这样,无论是通过移动构造函数还是RVO,都不会进行复制。

【讨论】:

  • “通过移动构造函数或 RVO”或两者:)
  • 你是对的。但是有没有办法返回为 vector* 而不是 shared_ptr >?
  • @zwx 是的,但你不应该使用shared_ptr。只需使用运算符new 分配它并返回它。这是一个坏主意。最好的方式是按值返回。
  • @StoryTeller 好吧,它们不会同时发生,对吧? :D
  • @mfontanini,取决于你如何同时定义 :D 例如,临时对象可能会被较弱的 RVO 消除,然后将结果移动到函数调用初始化的对象中。
【解决方案2】:

您从func() 返回的类型必须是boost::shared_ptr&lt;vector&lt;int&gt;&gt; - 而不是vector&lt;int&gt;*

共享指针的全部意义在于,您可以随意传递它们,当它们全部停止被引用时,它们指向的内存就会被回收。

当您在离开函数时“忘记”对共享指针的引用时,它将自动回收在该点分配的内存 - 为您留下指向无效内存位置的指针。

【讨论】:

    【解决方案3】:

    您的函数中的shared_ptr 是唯一一个引用指向您的vector 的指针。当它超出范围时(当函数返回时),它会删除引用的指针。

    让您的函数返回 shared_ptr 而不是常规指针。

    【讨论】:

      【解决方案4】:

      我建议你阅读一下应该如何使用 shared_ptr,因为你做错了。这意味着不再需要处理原始指针,绝对不要混合它们。基本上你传递 shared_ptr 实例,就像你过去使用原始指针一样,但不必再关心删除它了。改为这样做:

      typedef std::vector< int > my_vector;
      typedef boost::shared_ptr< my_vector > my_vector_ptr;
      
      my_vector_ptr func()
      {
        my_vector_ptr vec( boost::make_shared< my_vector >() );
        vec->push_back(123);
        return vec.get();
      }
      
      int _tmain(int argc, _TCHAR* argv[])
      {
        my_vector_ptr result = func();
        cout << result->at(0);
        return 0;
      }
      

      【讨论】:

        【解决方案5】:

        使用后向插入器来避免混合插入和返回相同的向量。让客户端指定它是什么类型的向量...从而使函数模板化。

        代码:

        typedef std::vector< int > my_vector;
        typedef boost::shared_ptr< my_vector > my_vector_ptr;
        
        template <typename OutputIterator>
        void func1(OutputIterator it)
        {
           // std::copy (anotherVector.begin(), anotherVector.end(), it);
           *it++ = 123; 
        }
        
        void func2(my_vector& v)
        {
           v.push_back(123);
        }
        
        int main()
        {
            my_vector_ptr vec( new my_vector() );
            func1(std::back_inserter(*vec)); // func is now an algorithm .. 
            func2(*vec);
        }
        

        func1 中,函数的签名说明了该函数的作用。你不能从矢量中删除,你不能做任何其他事情,只是它所说的。插入。

        func1 视为一种算法。

        【讨论】:

          猜你喜欢
          • 2010-10-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-16
          • 1970-01-01
          • 2018-12-13
          • 2021-11-15
          • 2010-10-13
          相关资源
          最近更新 更多