问题描述
#include <iostream>
using namespace std;
class A
{
public :
A()
{
cout<<"constructor is called"<<endl;
}
~A()
{
cout<<"destructor is called"<<endl;
}
A(const A &s)
{
cout<<"copy constructor is called"<<endl;
}
};
A beta()
{
A a;
cout<<"mem location a : "<<&a<<endl;
return a;
}
int main(int argc,char** argv) {
A b = beta();
cout<<"mem location b : "<<&b<<endl;
return 0;
}
constructor is called
mem location a : 0x7ffc12bdaf77
mem location b : 0x7ffc12bdaf77
destructor is called
据我了解,由于复制省略或返回值优化,仅创建了一个A实例,而没有为 A a 和 A b 创建2个实例。 但是从内存角度看上面的程序,对象a在函数beta的堆栈激活记录或堆栈空间内,并且内存位置为0x7ffc12bdaf77 。当它从beta返回时,复制省略使对象b与对象a相同,而不是复制它。因此,现在 b的地址也为0x7ffc12bdaf77 。我无法理解i f b仍然是main函数的局部变量,并且存在于其堆栈空间内,它如何在main的堆栈空间之外占用内存??
解决方法
在Microsoft x64调用约定中,将以隐藏指针作为 <form class="user-registration-form user-registration-form-login login" method="post">
<div class="ur-form-row">
<div class="ur-form-grid">
<p class="user-registration-form-row user-registration-form-row--wide form-row form-row-wide">
<label for="username">Username or email address <span class="required">*</span></label> <input placeholder="" type="text" class="user-registration-Input user-registration-Input--text input-text" name="username" id="username" value="" />
</p>
<p class="user-registration-form-row user-registration-form-row--wide form-row form-row-wide">
<label for="password">Password <span class="required">*</span></label> <span class="password-input-group">
<input placeholder="" class="user-registration-Input user-registration-Input--text input-text" type="password" name="password" id="password" />
</span>
</p>
<p class="form-row">
<input type="hidden" id="user-registration-login-nonce" name="user-registration-login-nonce" value="00cebd1a11" /><input type="hidden" name="_wp_http_referer" value="/my-account/" /> <input type="submit" class="user-registration-Button button" name="login" value="Login" />
<input type="hidden" name="redirect" value="" />
<label class="user-registration-form__label user-registration-form__label-for-checkbox inline">
<input class="user-registration-form__input user-registration-form__input-checkbox" name="rememberme" type="checkbox" id="rememberme" value="forever" /> <span>Remember me</span>
</label>
</p>
<p class="user-registration-LostPassword lost_password">
<a href="http://localhost/my-account/lost-password/">Lost your password?</a>
</p>
</p>
</div>
</div>
</form>
的第一个参数。该指针包含data scores;
length variables $ 16;
input variables $ low high score;
datalines;
Debt -10000 1 55
Debt 1 10000 23
MAX_NA -1 1 500
MAX_NA 1 100 -240
;
data main_data;
input ID Debt MAX_NA;
datalines;
222554 7584 12
212552 20 0
883123 500 7
913464 -200 -78
;
data end_result;
input ID Debt MAX_NA score;
datalines;
222554 7584 12 -217
212552 20 0 523
883123 500 7 -185
913464 -200 -78 555
;
的地址,该地址将位于beta
的堆栈帧上。该指针将用于立即在b
的堆栈帧上同时创建main
和a
。因此,换句话说,b
不存在于main
的堆栈帧中的任何位置;从内存的角度来看,a
和beta
将是等效的。
请考虑以下行:A b = beta();
。编译器如何实现?
嗯,beta
是其他功能。并且beta
的返回值为A
。因此,有两种方法可以实现此目的。编译器可以使beta
为其返回值A
分配堆栈空间,但是由于调用者需要使用该返回值,因此可能会出现问题。因此,相反,编译器使调用方为返回值分配堆栈空间。毕竟,调用者确实知道返回值的大小/对齐方式,因此它具有分配该空间所需的一切。
所以让我们去看看后者。这意味着,当编译器调用beta
时,它将传入beta
的返回值所在的地址。但这也意味着对于此beta
的特定调用,编译器可以只给beta
的返回值提供与给定b
相同的地址。
因此,在此处,我们已将副本从函数的返回值中删除到b
中。
因此,当编译器进行编译beta
时,它知道调用者将向其提供指向返回值应到达的位置的指针。因此,return a;
语句从a
变量语义上复制到此返回值对象中。
但是,编译器可以看到整个beta
。并且可以看到a
变量是局部变量,并且在所有控制路径上都将其返回。因此,编译器无需给a
提供单独的堆栈地址,只需将a
放在调用方提供的返回值内存中即可。
同样,我们从a
中删除了一个副本到返回值中。
据我了解,仅创建了一个A实例,而不是2个。
正确。
它如何在main的堆栈空间之外占用内存?
不是。
返回值仅在main
调用的堆栈帧中创建。