如何正确返回大向量

How to properly return a large vector

本文关键字:向量 返回 何正确      更新时间:2023-10-16
   vector<Foo*>&         getVectorOfFoo();

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

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

首先不要返回指针列表。
这使得允许的操作加倍不清楚。

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();
}

将其作为常量返回。

const vector<Foo *> &getVectorOfFoo();

如前所述,提供对容器的 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; } );

容器的返回类型合并到方法签名中几乎可以防止您在将来备用容器变得更合适时更改基础容器类型。

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

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

如果您确实希望返回容器,则需要精确地确定语义是什么,从听起来您希望它是只读的问题开始。在这种情况下,您几乎必须将容器复制到另一个包含常量指针而不是非常量指针的vector中,因此客户端无法修改它们。或者,另一个答案提供了使用提升指针容器的非常好的建议。