2015-12-22 39 views
-1

我想在C++中使用以下id函數。我會假設我可以簡單地做;簡單的方法返回在c + +中的數組

typedef int v3[3]; 

v3 & id(v3 & in) 
{ 
    in[0] = in[1] = in[2] = 1; 
    return in; 
} 

int main() 
{ 
    v3 & v = id(v); 
    return 0; 
} 

但是,這導致段錯誤與g++(這是不清楚給我)。因爲我可以做標量型如下:

int & zero(int & in) 
{ 
    in = 0; 
    return in; 
} 

int main() 
{ 
    int i = zero(i); 
    return 0; 
} 

如何使用id用一個單一的代碼行?我想避免一個醜陋的解決方案,如:

int main() 
{ 
    v3 v; 
    v3 & w = id(v); 
} 

當然,我不希望使用std::vectorstd::array(C++ 11)。所以我真的很感興趣,爲什麼我的天真的解決方案實際上是undefined behavior

編輯:std::vector將需要動態分配,在我的情況下應該避免(我需要操縱成千上萬的vr3)。我不能使用std::array,因爲我需要堅持c++03。顯然,人們無法猜測我的要求。

+0

您爲名爲'v'的引用分配存儲空間。它指向什麼,當你寫'v [0] = v [1] = v [2] = 1時,你寫的是什麼?'!? – StoryTeller

+0

如果您對「這是未定義的行爲?」感興趣嗎?和「編譯器爲什麼編譯它?」方面,請看這裏:http:// stackoverflow。com/questions/25717740/why-is-gcc-tricked-into-allowed-undefined-behavior-by-put-in-a-lo –

+0

我真的很感興趣,有什麼可能是不使用'std :: vector <>'或'std :: array <>'。它對你來說一定很明顯,你告訴我們,「當然」你不想使用它們。請在這個問題上稍微詳細一點。 – cdonat

回答

4

我真正感興趣的,爲什麼我天真的解決方案實際上是不確定的行爲。

這是因爲UB:您初始化參考vid的返回值,id返回的是它的參數參考。傳遞給id的參數爲v,因此您將其初始化爲v且未初始化自我,但未分配對象以供參考。

如何在一行代碼中使用id?

嗯,你可以簡單地在一行中鍵入兩個語句(和擺脫多餘的分配):

v3 v; id(v); 

但是,這將是簡單的:

v3 v{1, 1, 1}; 

我需要返回一個數組。

如果你仔細閱讀this page,你會發現你運氣不好。數組不能作爲參數返回或傳遞。你可以做的是使用一個封裝類來保存數組。但是沒有必要自己實現它,因爲標準庫已經提供了一個:std::array

當然,我不希望使用std ::向量或std ::陣列

與衝突的想你畫自己陷入了困境。那麼你需要自己重新實現std::array。我不建議你這樣做。

+0

感謝您的明確解釋!至少我現在明白我的錯誤。 – malat

5

此:

v3 & v = id(v); 

這:

int i = zero(i); 

是無稽之談,因爲你不能使用自己的初始化的東西。有些編譯器會警告你這個,但有些編譯器不會。

你可以做一個宏:

#define V3_UNIT {1,1,1} 

現在你可以這樣做:

v3 v = V3_UNIT; 

PTHREAD_MUTEX_INITIALIZER是這種技術在野外的一個常見的例子。

+0

你很幸運,你有警告。這會在運行時導致NULL引用異常,因爲v未初始化。 –

+0

@FigaroCat:什麼是C++中的「NULL引用異常」? –

+0

其實你*可以*使用它自己的初始化器中的東西 - 只要你使用它來初始化一個引用或指針。你不能使用*值*。 –

4

使用std::array

#include <array> 

using v3 = std::array<int, 3>; 

v3 id() 
{ 
    return {{ 1, 1, 1 }}; 
} 

int main() 
{ 
    v3 v = id(); 
} 
+0

正如我在文章中所說,我不能使用'std :: array'(或基於結構返回的解決方案)。我需要返回一個數組。 – malat

+0

@malat,但你沒有返回一個數組,你正在返回一個數組的引用。 – StoryTeller

+0

@malat它可能是'std :: array'或'std :: vector'(它應該是C++ 11之前的首選解決方案),或者是您的「醜陋」解決方案。這是你的選擇(除非你想動態分配內存,我真的不推薦)。 –

0

您可以在括號初始值{}。 像:in = {1,1,1};

2

你的問題是,在你的樣本main在v case你沒有v3任何地方。你只有v3 s的參考,並沒有什麼可供他們參考的。

你在int的情況下逃脫,因爲你有一個真正的int來引用。 (但它可能是不確定的行爲 - 那肯定是非常狡猾的。)

1

此代碼是未定義的行爲:

v3 & v = id(v); 

下鐺你會得到警告:

警告:參考「 v」其自身的初始化中使用時尚未綁定到一個值[-Wuninitialized]


[編輯]

其實我不是100%肯定,如果參考自賦值爲UB或形成不良的代碼,我發現關於這個話題有趣的討論:

Why is GCC tricked into allowing undefined behavior simply by putting it in a loop? http://www.open-std.org/pipermail/ub/2014-September/000506.html

這暗示它應該是相當不合格的 - 但看起來討論正在進行中。對這種代碼最常見的評論是nonsense,但我想只是因爲它很難找到適合這一部分的標準。

+0

所以UB相當於用'clang'發出警告?你可以再詳細一點嗎。 – malat

+0

@malat我已經更新了我的答案。警告並不總是表示UB。 – marcinj