2010-01-08 82 views
3

如何正確地將以下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 
} 

但我並不覺得一個完美的解決方案。

所以我的問題是:做什麼是最佳做法(通過避免不必要的複製操作)?如果可能的話,我想避免常規指針。我從未使用過智能指針,我不知道他們是否可以在這裏幫忙。

+3

由於經常NRVO這不是最現代的編譯器有問題...請參見本:http://www.efnetcpp.org/wiki/Return_value_optimization – 2010-01-08 03:39:49

回答

6

大多數C++編譯器都實現了return value optimization這意味着您可以高效地從函數中返回一個類,而無需複製所有對象的開銷。

我也建議你寫:

vector<int> v(getLargeVector()); 

這樣就可以拷貝構造對象,而不是默認的構造,然後運營商分配給它。

+6

std :: vector v = getLargeVector(); 我認爲這是做同樣的工作,更清晰。 – martsbradley 2010-01-08 15:59:43

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

現在是更好的方法。對於C++ 0x,第一種方法的問題將通過使用移動操作來代替複製操作。

1

爲什麼你想避免正常指針?是因爲你不想擔心內存管理,還是因爲你不熟悉指針語法?

如果你不想擔心內存管理,那麼智能指針是最好的方法。如果您對指針語法不舒服,請使用引用。

+0

恐怕可能的記憶因爲我應該全面通過這個向量。我絕對應該熟悉智能指針。 – Jabba 2010-01-08 03:46:35

1

您有最佳解決方案。傳遞參考是處理這種情況的方式。

0

聽起來像你可以用類來做到這一點......但這可能是不必要的。

#include <vector> 
using std::vector; 

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

可以依靠RVO來使此代碼易於編寫,但依靠RVO也可以咬你。 RVO是依賴於編譯器的功能,但更重要的是,具有RVO功能的編譯器可以根據代碼本身禁用RVO。例如,如果您要寫:

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

...那麼即使是支持RVO的編譯器也無法在此處進行優化。編譯器無法優化的條件還有很多,因此我可以通過設計依賴RVO的任何代碼來評估性能或功能異常。如果你購買了一個函數應該有一個工作(我只是做了一件事)的想法,那麼當你意識到你的代碼在設計中被破壞時,關於如何返回一個填充矢量的困境會變得更加簡單水平。你的函數確實做了兩件事:它實例化向量,然後它填充它。即使拋開所有這些瑣碎的事情,但是,依賴於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; 
} 
相關問題