2017-08-17 77 views
0

我已经知道一个存储类允许局部变量在程序的持续时间上保持现有的存储类别static为什么需要在从函数返回数组时声明一个数组为static。 (C++)

我想知道为什么需要声明digits[3]数组为静态。如果我没有声明它是静态的,除了编译错误,会发生什么。

P.S.我在处理C++中的指针或内存地址方面很新颖。

虽然我对C++中有关作用域的堆栈内存分配有点想法。

int* getDigits(int input) 
{ 
    const int TEN = 10; 
    int toStore; 
    int digits[3]; /* this array (static) */ 
    for (int i = 0; i < 3; ++i) 
    { 
     toStore = input % TEN; 
     digits[i] = toStore; 
     input = input/TEN; 
    } 
    return digits; 
} 

int main(int argc, char const *argv[]) 
{ 
    int* ptr; 
    ptr = getDigits(123); 
    for (int i = 0; i < 3; ++i) 
    { 
     std::cout << *(ptr+i) << std::endl; 
    } 

    return 0; 
} 
+5

1.将所有代码作为文本发布。代码图像几乎没有用处。 2.你为什么认为它需要是静态的? – Carcigenicate

+1

你应该使用'std :: vector'或'std :: array'。如果你不声明它是静态的,当函数返回并且你返回的指针是悬空的(即在函数外面没用)时,它将会消失。 – user463035818

回答

4

您正在返回一个指向函数本地数组的指针。如果将其声明为static,则表示数组的生命周期一直延续到程序结束,因此调用代码可以取消引用从该函数返回的指针。如果不声明它为static,则它是一个“自动”变量,其生命周期在块(函数体)结束时结束,因此取消引用返回的数据指针是未定义的行为。

无论如何,这些东西都不是典型的正确解决方案。首先,如果函数被调用两次,第二次调用可能会改变第一个结果指向的数据。更典型的解决方案是让该函数将一个指针(可能是shared_ptrunique_ptr)返回给使用new int[3]动态分配的数组。另一种解决方案是创建并返回一个std::array<int, 3>函数,这是一个可以通过值返回的正确的类类型(只有C样式的数组不能轻易地由函数返回)。

+2

返回一个指向自动存储持续时间变量的指针不会给出未定义的行为。尽管任何尝试解引用返回的指针(这可能是调用代码中可能发生的最常见的事情)。 – Peter

+0

@彼得:公平点,更新那里的语言。谢谢。 –

2

有迹象表明,在局部变量使用的static关键字将影响2分:寿命和可变的初始化

1. 如果将声明一个变量非静态在像一个函数:

int* getDigits(int input) 
{ 
    int digits[3]; /* local variable that dies on return */ 
    ... 
    return digits; 
} 

阵列digits未初始化和它的寿命被限制在内部的功能因为它位于堆栈。如果从函数返回,则对象的生命周期结束,并且通过返回的指针访问undefined,这可能并可能会在程序崩溃时结束。

2. 但是如果你声明数组静态,如:

int* getDigits(int input) 
{ 
    static int digits[3]; /* local variable that survives return */ 
    ... 
    return digits; 
} 

这将是零初始化,它的一生将生存函数的结束,因为它的内存是在数据段不是堆栈段。您返回的指针将指向有效内存。


的第一解决方案将在不确定的行为结束,并且第二溶液不是最佳的作为对getDigits()功能的第二呼叫将在至极可以从第一呼叫点的指针来改变静态变量digits

new int[3]动态分配内存或传递要改变的数组作为参数会更好。此外,还可以使用C++的std::array<int, 3>std::vector<int>(3),这些值将按值复制。这一切都将导致函数的几次调用都返回新的变量。

相关问题