类局部变量的指针
Pointer of class local variable?
可能重复:
可以使用局部变量';内存是否在其范围之外被访问?
做这样的代码(getIDs((返回指针(有什么令人担忧的事情吗:
class Worker{
private:
int workerID;
int departID;
int supervisorID;
public:
Worker()
{
workerID=0;
departID=0;
supervisorID=0;
name="anonymous";
workerAddress="none";
}
void setIDs(int worker, int depart, int supervisor)
{
workerID=worker;
departID=depart;
supervisorID=supervisor;
}
int* getIDs()
{
int id[3];
id[0]=workerID;
id[1]=departID;
id[2]=supervisorID;
return id;
}
};
然后,这样使用它:
Worker obj;
obj.setIDs(11,22,33);
cout<<(*obj.getIDs())<<endl;
cout<<++(*obj.getIDs())<<endl;
cout<<++(++(*obj.getIDs()))<<endl;
我想知道这一点,因为编译器显示:
警告1警告C4172:返回本地变量或的地址临时
您的int id[3]
在堆栈上分配,并在int* getIDs()
返回时被销毁。
返回一个指向变量的指针,该变量在getIDs()
返回后立即被销毁。指针然后变得悬空,实际上是无用的,因为用它做任何事情都是未定义的行为。
假设你这样定义你的类:
class Worker{
private:
int IDs[3];
public
// ...
int* getIDs() { return IDs; }
};
这个部分地解决了您的问题,因为只要Worker
对象在作用域中,指针就会保持有效,但这仍然是一种糟糕的做法。示例:
int* ptr;
while (true) {
Worker obj;
obj.setIDs(11,22,33);
ptr = obj.getIDs();
cout << *ptr; // ok, obj is still alive.
break;
} // obj gets destroyed here
cout << *ptr; // NOT ok, dereferencing a dangling pointer
解决此问题的更好方法是实现您的自定义运算符<lt;为你的班级。类似这样的东西:
class Worker {
private:
int workerID;
int departID;
int supervisorID;
public:
// ...
friend ostream& operator<<(ostream& out, Worker w);
};
ostream& operator<<(ostream& out, const Worker& w)
{
out << w.workerID << "n" << w.departID << "n" << w.supervisorID;
return out;
}
即使这样做有效,在c++中这样做也不是一个好的做法,除非你想要指向int的指针有一些深刻的原因。原始c样式数组比std::vector
s更难处理,所以使用它们,比如
std::vector<int> getIDs(){
std::vector<int> id(3);
id[0]=workerID; id[1]=departID; id[2]=supervisorID;
return id;
}
如果你担心开销:这可能会被现代编译器完全优化掉。
一旦离开定义局部变量的函数,它就会被销毁。所以你的指针会指向这个被破坏的位置,当然在函数外引用这样的位置是不正确的,会导致未定义的行为。
这里的基本问题是,当您输入一个函数调用时,您会在堆栈上获得一个新的框架(所有本地变量都将保存在其中(。任何未在函数中动态分配(使用new/malloc(的内容都将存在于该堆栈帧中,并且在函数返回时会被销毁。
函数返回一个指针,指向您在即将消失的堆栈帧中声明的3元素数组的开头。因此,这是未定义的行为。
虽然你可能会感到"幸运/不幸运",但当你使用指针时,你的数据仍然在指针指向的地方,但你也可能会遇到相反的情况。由于堆栈帧被破坏时会放弃空间,因此可以重用它,因此代码的另一部分可能会使用存储该数组中三个元素的内存位置,这意味着当您取消引用该指针时,它们将具有完全不同的值。
如果你运气好的话,你的程序只会出错/崩溃,所以你知道你犯了一个错误。
重新设计你的函数,以返回一个3 int的结构,一个向量,或者至少(我不建议这样做(,用new动态分配数组内容,这样它在函数调用后仍然存在(但你最好稍后删除它,否则小妖精会来找你…(。
当您想要返回一个数组,或者更确切地说是一个指针时,有两个路由。
一条路线:新
int* n = new int[3];
n[0] = 0;
// etc..
return n;
由于n现在是一个堆对象,以后由您删除它,如果您不删除它,最终会导致内存泄漏。
现在,我发现第二条路线是一种更容易的方法,但风险更大。它是您传入数组并在中复制值的地方。
void copyIDs(int arr[3] /* or int* arr */)
{
arr[0] = workerID;
/* etc */
}
现在您的数组已经填充,并且没有堆分配,所以没有问题。
编辑:将局部变量作为地址返回是错误的。为什么?
给定函数:
int* foo() {
int x = 5;
return &x; // Returns the address (in memory) of x
} // At this point, however, x is popped off the stack, so its address is undefined
// (Garbage)
// So here's our code calling it
int *x = foo(); // points to the garbage memory, might still contain the values we need
// But what if I go ahead and do this?
int bar[100]; // Pushed onto the stack
bool flag = true; // Pushed onto the stack
std::cout << *x << 'n'; // Is this guaranteed to be the value we expect?
总的来说,风险太大。不要这样做。
- 获取具有静态局部变量的绑定/推断捕获 lambda 的函数指针
- 将共享指针传递给函数参数 - 将其分配给局部变量的正确方法是什么
- C++ - 指向函数中局部变量的指针
- 指针 与局部变量的关系
- 指针被分配给错误的局部变量
- 通过静态局部变量的参考/指针返回
- 指针或局部变量,用于函数的输出参数
- 通过指针修改子函数中函数的局部变量的内容
- 局部变量与指针性能
- 为什么由指针和对象构建的局部变量显示不同的输出
- 返回局部变量C++的指针
- 为什么我们使用指针而不是局部变量
- 指向C++中局部变量的指针
- 指针可以将局部变量的内存指向其范围之外?
- 列表、指针和局部变量
- 我如何使一个函数指针引用一个局部变量
- 类局部变量的指针
- 函数中指向局部变量的全局指针
- 如何在g++中设置警告,以警告返回指向局部变量的指针
- 通过创建局部变量减少堆栈指针