2012-02-12 76 views
1

我需要編寫一個函數,添加兩個3D數組的元素,將結果存儲在第三個3D數組中,將結果存儲並複製到一維向量中,然後返回此向量通過不斷的參考。我遇到的問題是如何使用動態內存分配來返回矢量,因爲您無法返回局部變量。這是代碼的樣子,如果你能返回一個局部變量:動態內存分配在C++中的向量

template <class T> 
const vector<T>& allOperations(T*** const &x, T*** const &y, T*** &z, int height, int width, int depth) 
{ 
    vector<T> results(height*width*depth); 

    // Add the values of array x and y 
    for (int i = 0; i < height; i++) 
    { 
     for (int j = 0; j < width; j++) 
     { 
      for (int k = 0; k < depth; k++) 
      { 
       z[i][j][k] = x[i][j][k] + y[i][j][k]; 
      } 
     } 
    } 

    int l = 0; 
    //Places the values of array z into a vector 
    for (int i = 0; i < height; i++) 
    { 
     for (int j = 0; j < width; j++) 
     { 
      for (int k = 0; k < depth; k++) 
      { 
       results[l] = z[i][j][k]; 
       l++; 
      } 
     } 
    } 
    return results; 
} 

這是我在使用動態內存分配不正確的嘗試:

template <class T> 
const vector<T>& allOperations(T*** const &x, T*** const &y, T*** &z, int height, int width, int depth) 
{ 
    vector<T>* results(height*width*depth) = new vector<T>; 

    // Add the values of array x and y 
    for (int i = 0; i < height; i++) 
    { 
     for (int j = 0; j < width; j++) 
     { 
      for (int k = 0; k < depth; k++) 
      { 
       z[i][j][k] = x[i][j][k] + y[i][j][k]; 
      } 
     } 
    } 

    int l = 0; 
    //Places the values of array z into a vector 
    for (int i = 0; i < height; i++) 
    { 
     for (int j = 0; j < width; j++) 
     { 
      for (int k = 0; k < depth; k++) 
      { 
       *results[l] = z[i][j][k]; 
       l++; 
      } 
     } 
    } 
    return *results; 
} 
+0

所有STL容器的內容被自動保存在堆上,所以你可以簡單地返回'矢量'沒有內存開銷。 'const'也會起作用。但還沒有嘗試過。有人告訴我,由於兩個原因,不應該將STL容器與動態內存分配結合使用。首先:代碼變得難以置信,尤其是。對於多維數組。第二:這是雙重工作,因爲位於堆棧上的容器只是將引用存儲在本地函數堆棧中,而其他所有內容都是在堆上爲您創建的。 – guitarflow 2012-02-12 20:59:08

+0

這是否是功課?如果是這樣,它將解釋奇怪的要求,即通過不斷引用返回新創建的向量。 – 2012-02-12 22:29:57

回答

2

它沒有意義返回到基準一個局部變量。如果你訴諸你的第二個解決方案(返回一個參考new'矢量),那麼你幾乎肯定會有內存泄漏。按照慣例,獲取引用通常意味着其他實體已經在管理返回的對象的生命週期。

您可以採取多種措施來解決此問題。


不執行動態內存分配,更改函數簽名。

// Return a copy of the vector. 
vector<T> allOperations(T*** const &x, T*** const &y, T*** &z, int height, int width, int depth) 
{ 
    vector<T> results(height*width*depth); 
    // ... 
    return results; 
} 

如果編譯器執行copy elision和/或支持C++11 move constructors,「複製」,就永遠不會和回報將是非常有效的。


如果你真的要動態分配的載體,以滿足其他一些限制,你也需要改變函數簽名:

// Return a pointer to a newly allocated vector. 
const vector<T>* allOperations(T*** const &x, T*** const &y, T*** &z, int height, int width, int depth) 
{ 
    vector<T>* results(height*width*depth) = new vector<T>; 
    // ... 
    return results; 
} 

如果你這樣做,考慮返回smart pointer而不是返回一個裸指針。


如果這是一個成員函數,那麼也許你可以將矢量存儲在對象中。

template<typename T> 
class SomeClass 
{ 
    std::vector<T> results; 
public: 
    // ... 

    // Modify member and return reference to internal member. 
    const vector<T>& allOperations(T*** const &x, T*** const &y, T*** &z, int height, int width, int depth) 
    { 
     results.resize(height*width*depth); 
     // ... 
     return results; 
    } 
}; 

另一種可能,但極力勸阻解決方案是一個參考返回一些全局變量。

std::vector<T> results; 

// Modify global and return reference to global variable. 
const vector<T>& allOperations(T*** const &x, T*** const &y, T*** &z, int height, int width, int depth) 
{ 
    results.resize(height*width*depth); 
    // ... 
    return results; 
} 

或者在其僞裝(但完全等同)形式:

// Modify global and return reference to global variable. 
const vector<T>& allOperations(T*** const &x, T*** const &y, T*** &z, int height, int width, int depth) 
{ 
    // Global variable with name not visible outside the function. 
    static std::vector<T> results; 

    results.resize(height*width*depth); 
    // ... 
    return results; 
} 
+0

函數必須返回一個常量引用,而不僅僅是變量。這就是爲什麼我必須動態分配矢量。你的第二個例子返回一個指向新分配向量的指針,但是如果我想要返回一個新分配向量的引用,代碼應該是什麼樣子? – user1205613 2012-02-12 22:03:33

+0

@ user1205613:我確實意識到,在函數中動態分配的矢量將不得不在函數外部作爲某個點被刪除,否則會導致內存泄漏。 – 2012-02-12 22:20:30

+0

@ user1205613:你在語法上* can *可以返回一個常量引用到一個'new''d向量,但你永遠不會這麼做,因爲調用者不會「擁有」內存。如果你的'allOperations()'函數實際上是一個對象方法,那麼你可以讓該對象擁有該向量,但這似乎並非如此。如上所述,您的要求是不明確的。您希望函數返回對現有對象的引用,並且您還希望使用相同的函數來創建對象。這沒有意義。 – 2012-02-12 23:13:36

0

使用字符串,而不是使用malloc /新的載體。

int t; std::cin >> t; 
std::vector<std::string> strings(t); //Create t strings 
for(int i = 0; i < t; i++) 
std::cin >> strings[i]; //Read into each string