如何从类中返回大型向量而不复制数据

时间:2016-09-11 04:03:49

标签: c++ c++11 vector

我正在编写一个程序,其中一个类有一个大std::vector的数据成员(大约100k - 1M项)。其他类需要能够访问此向量。目前我有一个标准的访问器函数返回向量,但是这会返回我相信的向量的副本。我认为只返回迭代器或指向第一个元素的指针会有更多的内存和时间效率。但是,如果我这样做,那么如何使用这个指针来运行vector并知道何时停止(即向量结束的位置)?

我的代码如下所示:

class MyClass
{
    private:
        std::vector<MyObj> objects_;
        //...

    public:
        std::vector<MyObj> getObjects() { return objects_; }
        //...
}

当我想要运行(模拟)连接向量时,这个问题以另一种形式出现。如果我有vector MyClass,我希望能够迭代所有包含的object_向量。我从this answer知道boost :: join做了我的想法,但我想我需要返回副本才能工作。我可以返回一个指向向量的指针,并且仍然能够连续迭代它和其他的吗?

4 个答案:

答案 0 :(得分:7)

为避免性能损失,请返回参考文献。

// Non-const version
std::vector<MyObj>& getObjects() { return objects_;}

// const version
std::vector<MyObj> const& getObjects() const { return objects_; }

但是,在进行更改之前,必须考虑公开对成员变量的引用的缺点。它使你的课程变得不那么灵活。如果更有意义而不影响该类的所有用户,则无法轻松将objects_更改为其他类型的容器。

答案 1 :(得分:2)

通过委派给vector数据成员,使您的类充当集合。 当然,您可能需要重新访问使用MyClass的代码 但是,在getObjects()注释掉的情况下,编译器会告诉您哪些+大多数更改可能位于

MyClass heapsOfThem;
// ...
// just delete the `getObjects()` *and use MyClass::iterator*
// instead of std::vector::iterator.
// for(std::vector<MyObj>::iterator it=
//    heapsOfThem.getObjects().begin()...
// )
for(MyClass::iterator it=heapsOfThem.begin()...)

委托代码如下所示 - 一旦您修改了调用代码,您就可以改变主意,使用哪种类型(向量,列表,集)作为对象的内部容器,而无需更改调用代码。

class MyClass
{
    private:
        std::vector<MyObj> objects_;
        //...

    public:


        const size_t size() const {
          return objects_,size();
        }
        MyObj& operator[](size_t i) {
          return objects_[i];
        }
        const MyObj& operator[](size_t i) const {
          return objects_[i];
        }

        using iterator = std::vector<MyObj>::iterator;
        iterator begin() {
          return objects_.begin();
        }
        iterator end() {
          return objects_.end();
        }
        // TODO const iterators following the same pattern

        // *if you aren't good enough with the above*
        // uncomment it and let it return a *reference* 
        // std::vector<MyObj>& getObjects() { return objects_; }
        //...
}

答案 2 :(得分:0)

您可以重构该类以获得返回数组元素的公共方法以及数组的大小,因此所有其他类都可以获取值,而无需复制整个向量。

<nav class="navbar navbar-default">
                      <div class="container-fluid">
                        <div class="navbar-header" style="padding-left: 10px">
                          <button type="button" class="pull-left navbar-toggle" data-toggle="collapse" data-target="#myNavbar">
                            <span class="icon-bar"></span>
                            <span class="icon-bar"></span>
                            <span class="icon-bar"></span>
                          </button>          
                        </div>
                        <div class="collapse navbar-collapse" id="myNavbar">
                            <ul class="nav navbar-nav">            
                                <li><asp:Literal ID="litMenuBar" runat="server"></asp:Literal></li>
                            </ul>

                            <ul class="nav navbar-nav navbar-right">
                                <li><a href="#"><span class="glyphicon glyphicon-user"></span> My Account</a></li>            
                            </ul>
                        </div>
                      </div>
                    </nav>

使用这种方法,只有一个向量实例,但任何协作都可以通过两个公开方法来完成,这两个方法通过索引公开大小和值的访问者。

这种方法适用于for循环而不是迭代器。

public:
    unsigned int getMyObjArraySize();
    MyObj getMyObjElementAt(unsigned int index);

答案 3 :(得分:0)

返回指向矢量的指针没有问题。

std::vector<MyObj>* getObjects() { return &objects_; }

然后当想要迭代它时,只需取消引用:

std::vector<MyObj>* objectsPtr = getObjects();
for (auto& it : *objectsPtr)
{
   ...
}

但是,请确保在读取向量时不要写入向量,因为这会使迭代器无效。