此代码获取函数返回的值,创建并将其放入名为变量'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的地址空间在代码中被覆盖,因为它仍然知道它正被使用?
答案 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 behavior
,kek
是一个局部变量,一旦退出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()
方法。