C++,访问在其他方法中声明的非全局变量
C++, Accessing a non-global variable declared inside other method
此代码获取函数返回的值,创建并将其放入名为变量"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的地址空间在以后的代码中被覆盖吗?因为它仍然知道它在被使用吗?
这是未定义的行为:一旦函数完成,通过指针或引用访问其中的变量会使程序无效,并可能导致崩溃。
然而,当您"返回"堆栈时访问变量是完全有效的:
void assign(int* ptr) {
*ptr = 1234;
}
int main() {
int kek = 5;
cout << kek << endl;
assign(&kek);
cout << kek << endl;
}
请注意assign
是如何访问在另一个函数中声明的局部变量的值的。这是合法的,因为访问发生时main
尚未完成。
不,它不安全。函数执行完毕后,不再指向int
,而只是指向内存中的某个随机位置。它的值可以是任何值,因为它可以在程序的其他地方进行修改。
绝对不安全。将导致未定义的行为。
当"创建"一个局部变量时,编译器会在堆栈上给变量一些空间[1]。只要您在该函数内,该空间就可用于变量。当函数返回时,空间被释放,可供其他函数使用。因此,第二个代码中b
的地址将返回一个指向内存的指针,该指针将在返回完成后释放。
试着添加这样的东西:
int foo()
{
int x = 42;
cout << "x = " << x << endl;
return x;
}
并在调用topkek
之后调用foo
,可以肯定的是,kek
中的值(或由kek
指向的值)将发生变化。
[1] 对于学究们来说:是的,C++标准没有规定需要一个堆栈,也没有规定如何使用局部变量,等等。但总的来说,在当今几乎所有可用的编译器中,这就是它的工作方式。
这将是安全的:
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
};
当退出函数范围时,本地分配的自动类型将自动解除分配。然后返回的指针将指向已释放的内存。访问此内存将导致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.
这是未定义的行为。从函数返回后,kek
不再存在,指针返回涅盘,指向kek
曾经所在的位置。访问它会产生未定义的行为。未定义的行为意味着,任何都可能发生。你确实可以得到kek
中曾经的值,或者你的应用程序崩溃,或者你得到一些垃圾值,或者编译器认为可以在网上给你点一个披萨,再加上额外的奶酪。
这是undefined behavior
,kek
是一个局部变量,一旦退出topkek
,它所在的内存将被释放。它可能看起来是有效的,但由于它是未定义的,任何事情都可能导致,它可以在任何时候中断,你不能依赖结果。
首先,正如其他人所指出的,这肯定是不安全的。但根据您的使用情况,我认为您实际上可能正在尝试定义一个对象。例如,这段代码可能就是您想要的:
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()
方法中。
- 将变量声明为全局变量,然后声明为局部变量 -Shadowing-
- 将静态全局变量声明为内联有什么意义吗?
- 我真的可以使用 Type 的每个声明创建一个全局变量吗?
- 声明为类字段而不是全局变量
- 有什么理由C++ 11+ std::mutex 应该声明为全局变量,而不是作为函数参数传递到 std::thread 中
- 在结构声明的分号之前声明的结构变量是否为全局变量
- 困惑,为什么没有在此范围内声明 c++ 全局变量
- 使用静态和避免单例模式声明全局变量
- 声明全局变量 <vector>,代码将无法成功运行
- 即使在定义类后也无法在C++中声明全局变量?
- 查找声明全局变量的文件
- 我应该如何在我的C++项目中声明全局变量
- 使用预处理器技巧定义和声明全局变量
- 如何在C++中声明全局变量
- 在c++中声明全局变量时出现问题
- 声明全局变量,在方法中初始化
- 在C中声明全局变量会改变入口点吗?
- 在这种情况下,如何声明全局变量
- 声明全局变量<vector>问题
- 在C++中定义和声明全局变量