如何正确返回大矢量

时间:2011-06-23 14:32:06

标签: c++ stl vector

   vector<Foo*>&         getVectorOfFoo();

我想向其他人提供我的Foo对象列表。这是最好的方法吗?我在这里返回一个参考而不是复制正确吗?

来电者可以(意外)修改此列表吗?有没有办法避免这种可能性?我可以返回const向量吗?但是他们总是可以修改Foo对象,而我在那里做的也不多。 10-20个不同的人将编写使用此Foo列表的代码。

4 个答案:

答案 0 :(得分:9)

首先不要返回指针列表 这使得对允许的行为更加不清楚。

Boost有一个解决方案(像往常一样) 返回一个指针容器。这会将指针公开为普通成员。

boost::ptr_vector<Foo> const&  getVectorOfFoo();

现在用户无法改变返回的矢量。

示例:

#include <boost/ptr_container/ptr_vector.hpp>

class Foo
{
    public:
        void plop()         {}
        void poop() const   {}
};

boost::ptr_vector<Foo> const&  getVectorOfFoo()
{
    static boost::ptr_vector<Foo>  instance;  // Create and fill container with FOO objects.
    instance.push_back(new Foo);
    return instance;
}

int main()
{
    boost::ptr_vector<Foo> const&  value = getVectorOfFoo();  

    value[0].plop();  // Fail. not a const method (comment out this line)
    value[0].poop();
}

答案 1 :(得分:1)

也将它作为常量返回。

const vector<Foo *> &getVectorOfFoo();

答案 2 :(得分:1)

如前所述,提供对容器的const访问。

但它仍然不是“完美”,因为你需要将容器暴露给世界,所以如果你改变它,你就会强迫用户代码改变,如果界面不再相同的话。

但最后的希望是:

如果你可以使用lambdas(C ++ 0x),那么你最好提供一个for_each算法:

class MyThingManager
{
public:

   template< typename FunctorType > // note : could be non-template, in wich case use std::function<>
   void modify_each_thing( FunctorType f ) // if you use std::function, you can put the implementation in the cpp file instead of the header/inline
   {
       // do some checks, or maybe generate a list of Things that you allow to modify

       // then apply the function (here we assume we don't have a separate list - implementation defined for the win!)
       std::for_each( m_things.begin(), m_things.end(), f ); // oh yeah
       // then we can apply anything more we want
       check_everything_is_still_valid();
       notify_the_world();
   }

   // here is a simpler read-only version
   template< typename FunctorType >
   void for_each_thing( FunctorType f ) const { std::for_each( m_things.begin(), m_things.end(), f ); }


   // in case you want the user to know how many things to manipulate
   size_t things_count() const { return m_things;} 



private:

   std::vector<Thing> m_things; // could be any container, that's isolated from the algorithm!

};

用法:

 MyThingManager manager;
 manager.for_each_thing( []( const Thing& thing ){ std::cout << "\nA thing : " << thing; } );

答案 3 :(得分:1)

如果备用容器将来更合适,那么将容器的返回类型合并到方法签名中几乎可以防止您更改底层容器类型。

您至少应该考虑使用typedef来隐藏实际的容器类型,并记录返回对象的最小功能,而不是直接返回vector

但您可以考虑提供迭代器界面,例如YourThing::const_iterator getFooBegin()getFooEnd()。这样客户端代码就无法修改底层容器OR对象,实际上甚至不需要知道容器类型是什么,从而允许将来具有更大的灵活性。

如果你更喜欢返回一个容器,你需要准确地确定语义是什么,从它听起来像你想要它只读的问题。在这种情况下,您几乎必须将容器的副本复制到另一个包含const指针而不是非const的vector中,因此客户端无法修改它们。或者另一个答案提供了一个非常好的建议来使用boost指针容器。