C ++,访问在其他方法中声明的非全局变量

时间:2013-08-12 14:27:24

标签: c++ pointers

此代码获取函数返回的值,创建并将其放入名为变量'b'的新地址空间

    int main()
{
    int b;
    b = topkek();
    std::cout << &b;


};

int topkek()
 {
    int kek = 2;

    return kek;

 };

现在我明白因为变量kek在topkek方法中,我无法从main()方法访问它。使用C ++和指针,我想出了如何在方法终止后访问方法中声明的变量,看看这段代码。

int main()
{
    int * a;
    a = topkek();  //a is now pointing at kek

    std::cout << *a; //outputs 2, the value of kek.

    *a = 3;

    std::cout << *a; //output 3, changed the value of kek.

    std::cin >> *a;


};

int * topkek()
 {
int kek = 2;
    int* b = &kek;  //intializing pointer b to point to kek's address in stack

    return b; //returning pointer to kek

};

这种方法安全吗?编译器是否会阻止kek的地址空间在代码中被覆盖,因为它仍然知道它正被使用?

9 个答案:

答案 0 :(得分:4)

这是未定义的行为:一旦函数完成,通过指针或引用访问其中的变量会使程序无效,并可能导致崩溃。

然而,当您在堆栈上“返回”时访问变量是完全有效的:

void assign(int* ptr) {
    *ptr = 1234;
}
int main() {
    int kek = 5;
    cout << kek << endl;
    assign(&kek);
    cout << kek << endl;
}

注意assign如何访问在另一个函数内声明的局部变量的值。这是合法的,因为main在访问发生时尚未完成。

答案 1 :(得分:4)

不,这不安全。函数执行完毕后,您不再指向int,而只是指向内存中的某个随机位置。它的价值可以是任何东西,因为它可以在程序的其他地方修改。

答案 2 :(得分:3)

绝对不安全。将导致未定义的行为。

答案 3 :(得分:3)

当“创建”局部变量时,编译器会通过在堆栈[1]上给变量一些空间来实现。只要您在该函数内部,该空间就可用于该变量。函数返回时,空间被释放,可供其他函数使用。因此,第二个代码中b的地址返回一个指向内存的指针,该指针将在返回完成后重新启动。

尝试添加以下内容:

int foo()
{
     int x = 42;
     cout << "x = " << x << endl;
     return x;
}

并在致电foo后致电topkek,并且非常肯定kek(或由kek指向)中的值会发生变化。

[1]对于学究者:是的,C ++标准没有规定需要堆栈,或者应该如何使用局部变量等等。但总的来说,在几乎所有可用的编译器中今天,这是它的工作原理。

答案 4 :(得分:2)

退出功能范围时,将自动取消分配本地分配的自动类型。您返回的指针将指向释放的内存。访问此内存将导致undefined behaviour

int* topkek() {
    int kek = 2; // Create a local int kek

    int* b = &kek;  // Declare pointer to kek

    return b; // Return pointer to local variable. <-- Never do this!
}; // kek is destroyed and the returned pointer points to deallocated memory.

答案 5 :(得分:1)

这是undefined behaviorkek是一个局部变量,一旦退出topkek,它将驻留的内存将被释放。看起来它可能有效,但由于未定义任何可能导致的结果,它可能随时中断,您无法依赖结果。

答案 6 :(得分:1)

这是未定义的行为。从函数返回后,kek不再存在,并且指针返回指向必杀技,指向kek曾经的位置。访问它会产生不确定的行为。未定义的行为意味着,任何都可能发生。您确实可以获得曾经在kek或您的应用程序崩溃的值,或者您获得一些垃圾值,或者您的编译器认为适合在线订购披萨,请加上额外的奶酪。

答案 7 :(得分:1)

这是安全的:

int * topkek()
{
    static int kek = 2;
    int* b = &kek;  //intializing pointer b to point to kek's address in stack
    return b; //returning pointer to kek
};

答案 8 :(得分:1)

首先,正如其他人所指出的那样,这肯定是不安全的。但根据您的使用情况,我认为您可能实际上正在尝试定义一个对象。例如,此代码可能是您想要的:

struct topkek{
    int kek;
    int *operator()() {
        kek = 2;
        return &kek;
    }
};

int main()
{
    topkek mykek;

    int *a = mykek(); // sets mykek.kek to 2, returns pointer to kek

    std::cout << *a;
    *a = 3;
    std::cout << *a;
    std::cin >> *a;
};

这将以完全安全的方式为您提供对基础kek变量的干净访问。您当然可以将所需的任何代码放入operator()方法。