我将重新开始使用c ++并考虑变量的范围。 如果我在一个函数中有一个变量然后我返回该变量,那么当它返回时变量不会“死”,因为它所在的范围已经结束了?
我试过这个函数返回一个字符串,它确实有效。 有谁能解释一下?或者至少指出一些可以向我解释的地方。
由于
答案 0 :(得分:42)
当函数终止时, 发生以下步骤:
函数的返回值是 复制到占位符中 为此目的放在堆栈上。
堆叠帧后的所有内容 指针弹出。这破坏了 所有局部变量和参数。
从中弹出返回值 堆栈并被指定为值 功能。如果是的价值 功能没有分配给任何东西, 没有任务,而且 价值丢失。
下一条指令的地址 执行从弹出栈, 并且CPU恢复执行 那条指令。
答案 1 :(得分:3)
返回值时,会复制一份。局部变量的范围结束,但会复制并返回到调用函数。例如:
int funcB() {
int j = 12;
return j;
}
void A() {
int i;
i = funcB();
}
将j(12)的值复制并返回给i,这样我将收到12的值。
答案 2 :(得分:3)
这实际上取决于您返回的变量类型。如果返回一个原语,则它是通过复制而不是通过引用返回的,因此该值被复制到堆栈的顶部(或者,更常见的是放入寄存器中),调用函数可以在其中获取它。如果在堆上分配一个对象或内存并返回一个指针,那么它就不会因为它在堆上而不是堆栈而死亡。但是,如果你在堆栈上分配一些东西并返回它,那将是一件坏事。例如,其中任何一个都非常糟糕:
int *myBadAddingFunction(int a, int b)
{
int result;
result = a + b;
return &result; // this is very bad and the result is undefined
}
char *myOtherBadFunction()
{
char myString[256];
strcpy(myString, "This is my string!");
return myString; // also allocated on the stack, also bad
}
答案 3 :(得分:3)
仅仅是针对面向内存模型的解释:当调用函数时,会为函数创建一个临时空间来放置其局部变量,称为 frame 。当函数(被调用者)返回其值时,它将返回值放在调用它的函数的框架中(调用者),然后销毁被调用者框架。
“框架被破坏”部分是您无法从函数返回指针或对局部变量的引用的原因。指针实际上是一个内存位置,因此一旦框架被销毁,返回局部变量的内存位置(根据定义:框架内的变量)就会变得不正确。由于被调用者帧一返回其值就被销毁,所以对局部变量的任何指针或引用都会立即错误。
答案 4 :(得分:2)
将局部变量复制到返回值。复制构造函数被调用用于非平凡的类。
如果您返回指向本地变量的指针或引用,您将遇到麻烦 - 正如您的直觉所暗示的那样。
答案 5 :(得分:2)
这取决于返回项目的类型。如果按值返回,则会生成变量的新副本以返回给调用者。在这种情况下你不需要担心对象的生命周期,但你可能需要担心复制对象的成本(但请不要过早地优化 - 正确性更重要):
std::string someFunc( std::string& const s)
{
return s + "copy";
}
如果函数返回一个引用,那么你需要注意你要返回的内容,因为它的生命周期需要超出函数的生命周期,如果你的话,调用者不一定能够delete
它'使用new
创建对象:
std::string& someFunc2( std::string const& s)
{
return s + "reference to a copy"; // this is bad - the temp object created will
// be destroyed after the expression the
// function call is in finishes.
// Some, but not all, compilers will warn
// about this.
}
当然,返回指针也会有类似的生命周期考虑因素。