2014-11-24 17 views
1

所以我寫了一個函數,它應該像一個一樣,返回一個數組(因爲你知道數組不允許用C++返回),爲此我需要一個臨時未命名的參數,它將被用作默認參數值最後一個參數含蓄,像這樣:C++如何聲明一個臨時未命名的,未初始化的數組?

template<size_t szArr, typename typeArrs> 
auto fnAdd2ArrayElements(const typeArrs (&arr_0)[szArr], const typeArrs (&arr_1)[szArr], typeArrs (&&result)[szArr] = {}) -> typeArrs (&&)[szArr] 
{ 
    for(size_t i(0); i < szArr; ++i) 
     result[i] = arr_0[i] + arr_1[i]; 

    return move(result); 
} 

正如你所看到的「結果」參數有一個默認的參數值未命名的數組,但將永遠「零填充」,因爲空方括號。這會降低性能,因爲你可以看到我的功能並不關心它的內容,並將填補所有內容。無論如何,我可以宣佈它未初始化。類似這樣的:

template<typename T, size_t sz> using identity = T [sz]; 

template<size_t szArr, typename typeArrs> 
auto fnAdd2ArrayElements(const typeArrs (&arr_0)[szArr], const typeArrs (&arr_1)[szArr], typeArrs (&&result)[szArr] = identity<typeArrs, szArr>()) -> typeArrs (&&)[szArr] 
{ 
    for(size_t i(0); i < szArr; ++i) 
     result[i] = arr_0[i] + arr_1[i]; 

    return move(result); 
} 

但是上面的代碼不會編譯。那麼,有什麼想法可以做到這一點?

編輯:看來還有其他問題出現。由於我們返回一個'xvalue'(而不是'prvalue'),如果我們將結果存儲在'rvalue'引用中,那麼未命名的臨時對象的生命期將不會延長,就好像我們已經按值返回了一個數組。這裏是一個例子:

const int iArr[] = {0, 1, 2, 3, 4}; 

const int iArr1[] = {0, 1, 2, 3, 4}; 

int (&&added)[5] = fnAdd2ArrayElements(iArr, iArr1); //this will create an dangling reference 

added[0]; //illegal - accessing dangling reference 
+1

爲什麼你(想你)必須返回一個數組?你打算如何使用它? [爲什麼不使用向量?] – 2014-11-24 08:38:51

+6

你有沒有考慮過'std :: array'? – Jarod42 2014-11-24 08:39:38

+0

是的,但我想直接使用內置陣列。 – AnArrayOfFunctions 2014-11-24 08:47:46

回答

3

這將是危險的,因爲這臨時的壽命短

template <typename T, size_t N> 
struct UninitializedArray 
{ 
    UninitializedArray() {} 
    T arr[N]; 
}; 

template <size_t szArr, typename typeArrs> 
typeArrs (&&)[szArr] 
fnAdd2ArrayElements(
    const typeArrs (&arr_0)[szArr], 
    const typeArrs (&arr_1)[szArr], 
    typeArrs (&&result)[szArr] = UninitializedArray<typeArrs, szArr>{}.arr) 
{ 
    std::cout << result[0] << std::endl; // To check that value is not initialized. 

    for (size_t i(0); i < szArr; ++i) { 
     result[i] = arr_0[i] + arr_1[i]; 
    } 
    return std::move(result); 
} 

Live example

+0

它不短,但完全等於使用的表達式(在調用函數的情況下)。 – AnArrayOfFunctions 2014-11-26 10:57:16

0

我不認爲有一個好的方法來做到這一點,因爲你不能正確指示返回一個數組。

另一種方法是重載函數,並在該重載內調用其他函數,並適當定義數組參數。 (這是Java可用的唯一方法)。

0

這裏的問題是,傳遞函數指針會使函數參數衰減指針(即使您的代碼稱它們爲引用,它們是指針)。你不能將一個指針「返回到數組中」 - 這實際上意味着編譯器必須執行memcpy(dest, fnAdd2ArrayElements(...), number_of_bytes);,但它不知道代碼中number_of_bytes的實際長度。

你的代碼,你已經使用三個數組參數,所以你可以簡單地使功能分爲

void fnAdd2ArrayElements(const typeArrs (&arr_0)[szArr], 
         const typeArrs (&arr_1)[szArr], 
         typeArrs (&result)[szArr]); 

你會的,但是,必須初始化原result

或者,這是我的首選解決方案:使用std::vector [或類似的]。

+0

否如果使用默認參數 - 未命名的臨時。 – AnArrayOfFunctions 2014-11-24 09:14:37

+0

對,所以編譯器會填充一個參數,你只需要不必鍵入它。這意味着它被創建並傳遞給函數[很明顯會受到優化,但是在循環中使用'result',所以編譯器至少不能刪除構造和破壞]。 C和C++從來沒有被設計爲做你正在做的事情,我不能看到它將實際工作的任何方式。 – 2014-11-24 09:21:10

+0

它確實 - 它編譯得很好。實際上,如果與參數不一樣,你認爲如何創建返回值?沒有什麼不可思議的,在堆棧中分配給它們的內存,就像這個函數爲未命名的變量分配內存一樣。 – AnArrayOfFunctions 2014-11-24 09:25:20