C++中的引用在初始化时占用内存吗?

这个问题,还没有完全研究完,先贴上一部分实验结果。

这里比较疑惑的有两个问题,c++中是怎么实现引用的和引用会和指针一样占用内存吗?

其实是一个问题,下面的实验都是在linux64 g++编译器平台

看第一段代码

#include<iostream>
using namespace std;

int main()
{
 int a=10;
 int* p =&a;
 int &q =a;

 cout<<&a<<endl;
 cout<<&p<<endl;
 cout<<&q<<endl;

 (*p)++;
 q++;
 cout<<a<<endl;
 return 0;
}

三个cout是将变量的地址打印出来

结果是

0x7fffffffe32c
0x7fffffffe330
0x7fffffffe32c
12

表面上看引用和变量是一个地址,看看目标代码的反汇编代码

int main()
{
  40087d:   55                      push   %rbp
  40087e:   48 89 e5                mov    %rsp,%rbp
  400881:   48 83 ec 20             sub    $0x20,%rsp
int a=10;
  400885:   c7 45 ec 0a 00 00 00    movl   $0xa,-0x14(%rbp)
int* p =&a;
  40088c:   48 8d 45 ec             lea    -0x14(%rbp),%rax
  400890:   48 89 45 f0             mov    %rax,-0x10(%rbp)
int &q =a;
  400894:   48 8d 45 ec             lea    -0x14(%rbp),%rax
  400898:   48 89 45 f8             mov    %rax,-0x8(%rbp)

cout<<&a<<endl;
  40089c:   48 8d 45 ec             lea    -0x14(%rbp),%rax
  4008a0:   48 89 c6                mov    %rax,%rsi
  4008a3:   bf 80 10 60 00          mov    $0x601080,%edi
  4008a8:   e8 b3 fe ff ff          callq  400760 <_ZNSolsEPKv@plt>
  4008ad:   be 80 07 40 00          mov    $0x400780,%esi
  4008b2:   48 89 c7                mov    %rax,%rdi
  4008b5:   e8 b6 fe ff ff          callq  400770 <_ZNSolsEPFRSoS_E@plt>
cout<<&p<<endl;
  4008ba:   48 8d 45 f0             lea    -0x10(%rbp),%rax
  4008be:   48 89 c6                mov    %rax,%rsi
  4008c1:   bf 80 10 60 00          mov    $0x601080,%edi
  4008c6:   e8 95 fe ff ff          callq  400760 <_ZNSolsEPKv@plt>
  4008cb:   be 80 07 40 00          mov    $0x400780,%esi
  4008d0:   48 89 c7                mov    %rax,%rdi
  4008d3:   e8 98 fe ff ff          callq  400770 <_ZNSolsEPFRSoS_E@plt>
cout<<&q<<endl;
  4008d8:   48 8b 45 f8             mov    -0x8(%rbp),%rax
  4008dc:   48 89 c6                mov    %rax,%rsi
  4008df:   bf 80 10 60 00          mov    $0x601080,%edi
  4008e4:   e8 77 fe ff ff          callq  400760 <_ZNSolsEPKv@plt>
  4008e9:   be 80 07 40 00          mov    $0x400780,%esi
  4008ee:   48 89 c7                mov    %rax,%rdi
  4008f1:   e8 7a fe ff ff          callq  400770 <_ZNSolsEPFRSoS_E@plt>
。。。。。
}

主要看这段代码

int &q =a;
  400894:   48 8d 45 ec             lea    -0x14(%rbp),%rax
  400898:   48 89 45 f8             mov    %rax,-0x8(%rbp)

实际q这个所谓的别名是占有内存的,

那么为什么输出其地址时,输出的引用变量的地址,看看反汇编代码就知道了

cout<<&q<<endl;
  4008d8:   48 8b 45 f8             mov    -0x8(%rbp),%rax
cout<<&p<<endl;
  4008ba:   48 8d 45 f0             lea    -0x10(%rbp),%rax

看看这两者的区别,对于取引用地址,是获取的原变量的地址,而取指针地址,则是将自己的内存地址输出去。

为了进一步说明这个问题 ,再用一段代码

struct  test1
{
 int a;
 int& p;
};
struct test2
{
 int a;
};
struct test3
{
 int a;
 int* p;
};
int main()
{
 cout<<sizeof(test1)<<endl;
 cout<<sizeof(test2)<<endl;
 cout<<sizeof(test3)<<endl;
}

运行结果为

16

4

16

好像看来引用是占内存的。。

可是真实这样吗?。。。。。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-27 12:10:20

C++中的引用在初始化时占用内存吗?的相关文章

解决CodeIgniter大量查询sql时占用内存大问题

最近的项目上面做大数据插入时总提示内存超出限制 不管怎样unset结果内存仍然很大! 最终发现是CI的机制导致,只要关闭掉问题解决了 $this->db->save_queries = FALSE; 它会把所有执行的SQL保存一份在内存做调试:果断关了! 这东西是从v1.6开始就有 Added $this->DB->save_queries variable to DB driver, enabling queries to get saved or not. Previously

C++中的引用

引用就是某个目标变量的别名,对引用的操作与对变量的直接操作效果完全相同. 引用的声明方法:类型标识符 &引用名=目标变量名: 如下:定义引用ra,它是变量a的引用,即别名. int a; int &ra=a; 1)  声明一个引用,必须进行初始化. 2)引用声明完毕后,相当于目标变量有两个名称即该目标原名称和引用名,且不能再把该引用名作为其他变量名的别名. 3)引用本身不是一种数据类型,因此引用本身不占存储单元,系统也不会给引用分配存储单元. 4)不能建立数组的引用.因为数组是一个由若干个

类成员变量中存在引用,const,和指针类型时需要注意的事项

背景知识 编译器默认生成函数的规则如下: 1.定义一个类时,如果自己没有声明,那么编译器会自动帮助生成一个拷贝构造函数(copy construction),赋值操作符(copy assignment),析构函数(deconstruction). 2.如果没有声明任何构造函数(包括拷贝构造函数),编译器会帮助声明一个默认构造函数. 构造函数(包括编译器生成的默认构造函数)的执行包括两个阶段: 1.初始化阶段 2.构造函数体内代码执行构造的阶段 构造函数执行的两个阶段非常重要,在初始化阶段,如果类

VS2015+OpenGL4.0开发编译时弹出错误:glaux.lib(tk.obj) : error LNK2019: 无法解析的外部符号 _sscanf,该符号在函数 [email&#160;protected] 中被引用

一.问题描述: VS2015+OpenGL4.0开发编译时弹出如下所示的错误: 1>glaux.lib(tk.obj) : error LNK2019: 无法解析的外部符号 _sscanf,该符号在函数 [email protected] 中被引用 1>glaux.lib(tk.obj) : error LNK2019: 无法解析的外部符号 _vsprintf,该符号在函数 _PrintMessage 中被引用 二.问题原因: VS2015默认编译时将许多标准库采用内联方式处理,因而没有可以链

基于vue项目的组件中导入mui框架初始化滑动等效果时需移除严格模式的问题

基于vue项目的组件中导入mui框架初始化滑动等效果时,控制台报错:Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them 可使用 babel-plugin -transform-remove-strict-mode 移除严格模式 可先进行$ n

使用SDL2出现 “error LNK2019: 无法解析的外部符号 _SDL_main,该符号在函数 _main 中被引用” 时的可能错误记录

这几天在使用SDL2,之前一直都没有错,直到上午把项目搬了个地方.结果一直出现 “error LNK2019: 无法解析的外部符号 _SDL_main,该符号在函数 _main 中被引用” . 看了网上的方法都说是没有正确定义 main 函数 ,这是SDL2main.lib指定需要的函数.结果我把他定义在了"xx.h"这样的头文件中. 原来我一直没理解头文件和源文件的重要区别.把 main 函数定义在 "xx.cpp" 这样的源文件中就可以正确编译了. 看来还需要再

初始化时的过程

new一个对象时jvm的工作步骤: 1:在栈内存定义变量此时为初始值,定义方法.基本数据类型 int 0 .引用数据类型为null; 2: 调用父类构造方法,定义父类的属性和方法(如果子类已经重写父类的方法 这时不会被覆盖,整个过程不会发生任何覆盖的情况).  父类的private方法是不能被重写的,你把父类的getNum改成protected 和private结果是不一样的!! 3:给父类的变量赋值. 4:执行父类构造方法中其他语句(此时它自己变量已经初始化和赋值完成,貌似很合理). 5:给自

java中虚引用PhantomReference与弱引用WeakReference(软引用SoftReference)的差别

之前的这篇博客介绍了java中4种引用的差别和使用场景,在最后的总结中提到: "软引用和弱引用差别不大,JVM都是先把SoftReference和WeakReference中的referent字段值设置成null,之后加入到引用队列:而虚引用则不同,如果某个堆中的对象,只有虚引用,那么JVM会将PhantomReference加入到引用队列中,JVM不会自动将referent字段值设置成null".这段总结写的比较仓促,也没有给出实际的例子加以佐证.本文主要是重申下这几种引用的差别,并

ios uiimage初始化时的两种方法

第一种方式:UIImage *image = [UIImage imageNamed:@"image"]; 使用这种方式,第一次读取的时候,先把这个图片存到缓存里,下次再使用时直接从缓存中读取:优点:只有第一次使用的时候稍慢,接下来在使用就会稍快:缺点:如果在当前工程中只使用一次会浪费内存. 第二种方式:initWithContentsOfFiles初始化时,每次都会根据路径去读取,不会占用内存,如果图片在当前工程中只使用一次,应该选择这个方法.