2017-03-28 181 views
1

在下面的代碼塊的地址...C++函數返回靜態數組

#include <iostream> 

int* a() 
{ 
    static int nums[] = { 1, 2, 3 }; 
    return nums; 
} 

int* const& b() 
{ 
    static int nums[] = { 4, 5, 6 }; 
    return nums; 
} 

void c(int*& num) 
{ 
    if (num) 
    { 
    std::cout << "I got " << *num << std::endl; 
    } 
} 

void d(int* const& num) 
{ 
    if (num) 
    { 
    std::cout << "I got " << *num << std::endl; 
    } 
} 

int main(int argc, char* argv[]) 
{ 
    int* nums = a(); 
    std::cout << nums[1] << std::endl; 

    int* const nums2 = b(); 
    std::cout << nums2[1] << std::endl; 

    int* num = new int(64); 
    c(num); 
    delete num; 

    int num2 = 101; 
    d(&num2); 
} 

...爲什麼功能int* const& b()生成以下編譯警告?

sh-4.2$ g++ -o main *.cpp                                             
main.cpp: In function 'int* const& b()':                                         
main.cpp:12:10: warning: returning reference to temporary [-Wreturn-local-addr]                               
    return nums; 

我圖numsb()是靜態的,因此在存儲器中的數據部分,所以不受返回一個真正的功能局部變量的地址的問題。

我試着在我的桌面和兩個在線C++編譯器上編譯並運行這段代碼。可執行文件在桌面和一個在線編譯器上運行良好,但在第二個在線編譯器上,它在打印「2」之後儘早死亡。但是我無法訪問核心文件,也沒有看到堆棧跟蹤來查看實際發生了什麼問題。 (工作在線編譯器是教程點和非工作在線編譯器是codechef)

我特別困惑爲什麼b()生成此警告和/或運行時錯誤,而a()沒有。

回答

4

發生這種情況的原因是nums不是指針,而是數組。雖然C++會根據需要隱式地將其轉換爲指針,但對數組引用並將其表示爲指針需要臨時指針。從本質上講,C++會做到這一點:

static int nums[] = { 4, 5, 6 }; 
int* invisible = nums; 
return invisible; 

製作一個靜態的指針,並採取對它的引用將解決這樣的警告:

static int data[] = { 4, 5, 6 }; 
static int* nums = data; 
return nums; 

或者,你可以的typedef一個固定長度的數組,並使用它作爲退貨類型的b()

typedef int array3[3]; 

array3 const& b() 
{ 
    static int nums[] = { 4, 5, 6 }; 
    return nums; 
} 
... 
array3 const &nums2 = b(); 
+0

這很有趣。我一直認爲,因爲C++做了隱含的轉換,它們是相同/可互換的。感謝這個答案:我學到了一些新東西。 – StoneThrow