从函数发回一个向量

时间:2010-01-08 03:24:48

标签: c++ reference vector

如何将以下Java代码正确地翻译成C ++?

Vector v;
v = getLargeVector();
...
Vector getLargeVector() {
    Vector v2 = new Vector();
    // fill v2
    return v2;
}

所以这里v是一个参考。该函数创建一个新的Vector对象并返回对它的引用。很干净。

但是,让我们看看以下C ++镜像转换:

vector<int> v;
v = getLargeVector();
...
vector<int> getLargeVector() {
    vector<int> v2;
    // fill v2
    return v2;
}

现在v是一个矢量对象,如果我理解正确,v = getLargeVector()复制函数返回的向量中的所有元素v ,这可能很贵。此外,在堆栈上创建v2并返回它将导致另一个副本(但我知道现代编译器可以优化它)。

目前这就是我的工作:

vector<int> v;
getLargeVector(v);
...
void getLargeVector(vector<int>& vec) {
    // fill vec
}

但我觉得这不是一个优雅的解决方案。

所以我的问题是:这样做的最佳做法是什么(通过避免不必要的复制操作)?如果可能的话,我想避免正常的指针。到目前为止,我从未使用智能指针,我不知道他们是否可以在这里提供帮助。

6 个答案:

答案 0 :(得分:6)

大多数C ++编译器都实现return value optimization,这意味着您可以从函数中有效地返回一个类,而无需复制所有对象的开销。

我还建议您写一下:

vector<int> v(getLargeVector());

这样你就可以复制构造对象而不是默认构造,然后运算符赋值给它。

答案 1 :(得分:3)

void getLargeVector(vector<int>& vec) { 
    // fill the vector
} 

目前是一种更好的方法。使用c ++ 0x,第一种方法的问题在于使用移动操作而不是复制操作。

答案 2 :(得分:2)

可以依赖RVO使这段代码编写简单,但依赖RVO也可以咬你。 RVO是依赖于编译器的功能,但更重要的是,支持RVO的编译器可以根据代码本身禁用RVO。例如,如果您要写:

MyBigObject Gimme(bool condition)
{
  if( condition )
    return MyBigObject( oneSetOfValues );
  else
    return MyBigObject( anotherSetOfValues );
}

...那么即使是支持RVO的编译器也无法在此进行优化。在许多其他条件下编译器将无法进行优化,因此通过我计算任何设计依赖于RVO以获得性能或功能的代码。

如果你认为一个函数应该只有一个作业(我只是这样做),那么当你意识到你的代码在设计层被破坏时,你对如何返回一个填充向量的困境变得更加简单。你的函数确实做了两个工作:它实例化向量,然后填充它。即使把所有这些迂回放在一边,然而,更通用的&amp;存在可靠的解决方案而不是依靠RVO。只需编写一个填充任意向量的函数。例如:

#include <cstdlib>
#include <vector>
#include <algorithm>
#include <iostream>

using namespace std;

template<typename Iter> Iter PopulateVector(Iter it, size_t howMany)
{
    for( size_t n = 0; n < howMany; ++n )
    {
        *(it++) = n;
    }

    return it;
}

int main()
{
    vector<int> ints;
    PopulateVector(back_inserter(ints), 42);
    cout << "The vector has " << ints.size() << " elements" << endl << "and they are..." << endl;
    copy(ints.begin(), ints.end(), ostream_iterator<int>(cout, " "));
    cout << endl << endl;

    static const size_t numOtherInts = 42;
    int otherInts[numOtherInts] = {0};
    PopulateVector(&otherInts[0], numOtherInts);
    cout << "The other vector has " << numOtherInts  << " elements" << endl << "and they are..." << endl;
    copy(&otherInts[0], &otherInts[numOtherInts], ostream_iterator<int>(cout, " "));

    return 0;
}

答案 3 :(得分:1)

为什么要避免正常指针?是因为你不想担心内存管理,还是因为你不熟悉指针语法?

如果您不想担心内存管理,那么智能指针是最好的方法。如果您对指针语法感到不舒服,请使用引用。

答案 4 :(得分:1)

你有最好的解决方案。通过引用传递是处理这种情况的方法。

答案 5 :(得分:0)

听起来你可以用一个班级做到这一点......但这可能是不必要的。

#include <vector>
using std::vector;

class MySpecialArray
{
    vector<int> v;
public:
    MySpecialArray()
    {
        //fill v
    }
    vector<int> const * getLargeVector()
    {
        return &v;
    }
};