这是个伪命题。
占也不占,不占也占,占还是不占,需要加个前提。
是物理上的内存,还是逻辑上的。在绝对物理上,一定是占的,不可能为0,在逻辑上,可能不占。
内部原理
编译时
C++ 引用变量的内部机制实际上是通过指针来实现的。
int a = 10;
int& b = a;
//在编译时,编译器会将第二行代码转换为以下代码:
int* b = &a;
使用时
引用在使用时会自动解引用。
引用变量在内部实现上是一个指针变量,在使用时可以像普通变量一样进行访问,无需使用指针运算符进行解引用操作
引用占用内存的例子
#include <iostream>
using namespace std;
void test1(int a, int &b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, int n, int &o, int p)
{
cout << &a << "\n";
cout << &b << "\n";
cout << &c << "\n";
cout << &d << "\n";
//--
cout << &e << "\n";
cout << &f << "\n";
cout << &g << "\n";
cout << &h << "\n";
//--
cout << &i << "\n";
cout << &j << "\n";
cout << &k << "\n";
cout << &l << "\n";
//--
cout << &m << "\n";
cout << &n << "\n";
cout << &o << "\n";
cout << &p << "\n";
}
void test2(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, int n, int o, int p)
{
cout << &a << "\n";
cout << &b << "\n";
cout << &c << "\n";
cout << &d << "\n";
//--
cout << &e << "\n";
cout << &f << "\n";
cout << &g << "\n";
cout << &h << "\n";
//--
cout << &i << "\n";
cout << &j << "\n";
cout << &k << "\n";
cout << &l << "\n";
//--
cout << &m << "\n";
cout << &n << "\n";
cout << &o << "\n";
cout << &p << "\n";
}
int main()
{
int x = 5;
int y = 6;
test1(1, x, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, y, 16);
cout << "---"<< "\n";
test2(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
return 0;
}
//输出
0x332a5ff620
0x332a5ff6ac
0x332a5ff630
0x332a5ff638
0x332a5ff640
0x332a5ff648
0x332a5ff650
0x332a5ff658
0x332a5ff660
0x332a5ff668
0x332a5ff670
0x332a5ff678
0x332a5ff680
0x332a5ff688
0x332a5ff6a8
0x332a5ff698
---
0x332a5ff620
0x332a5ff628
0x332a5ff630
0x332a5ff638
0x332a5ff640
0x332a5ff648
0x332a5ff650
0x332a5ff658
0x332a5ff660
0x332a5ff668
0x332a5ff670
0x332a5ff678
0x332a5ff680
0x332a5ff688
0x332a5ff690
0x332a5ff698
我的系统是64位的,指针变量占用8个字节的空间,查询代码如下:
#include <iostream>
using namespace std;
/**
* 基本类型占用的内存空间
*/
int main() {
std::cout << "Size of int: " << sizeof(int) << " bytes" << std::endl;
std::cout << "Size of short: " << sizeof(short) << " bytes" << std::endl;
std::cout << "Size of long: " << sizeof(long) << " bytes" << std::endl;
std::cout << "Size of long long: " << sizeof(long long) << " bytes" << std::endl;
std::cout << "Size of float: " << sizeof(float) << " bytes" << std::endl;
std::cout << "Size of double: " << sizeof(double) << " bytes" << std::endl;
std::cout << "Size of long double: " << sizeof(long double) << " bytes" << std::endl;
std::cout << "Size of char: " << sizeof(char) << " bytes" << std::endl;
std::cout << "Size of bool: " << sizeof(bool) << " bytes" << std::endl;
cout<<"-------"<<"\n";
std::cout << "Size of int*: " << sizeof(int*) << " bytes" << std::endl;
std::cout << "Size of short*: " << sizeof(short*) << " bytes" << std::endl;
std::cout << "Size of long*: " << sizeof(long*) << " bytes" << std::endl;
std::cout << "Size of long long*: " << sizeof(long long*) << " bytes" << std::endl;
std::cout << "Size of float*: " << sizeof(float*) << " bytes" << std::endl;
std::cout << "Size of double*: " << sizeof(double*) << " bytes" << std::endl;
std::cout << "Size of long double*: " << sizeof(long double*) << " bytes" << std::endl;
std::cout << "Size of char*: " << sizeof(char*) << " bytes" << std::endl;
std::cout << "Size of bool*: " << sizeof(bool*) << " bytes" << std::endl;
return 0;
}
都是sizeof 惹的祸
之所以会有这个占不占内存的疑问。多数是因为sizeof的时候无法读取到引用占用的空间。
这就给人一种错觉,就是引用不占用内存空间。
为什么引用无法sizeof
sizeof无法读取引用所占用的空间,即使是引用内部表示为指针的内存占用。重点在于无法读取,而非不占用。
无法读取的原因就在于:
引用的自动解引用
每当我们sizeof(引用)
的时候,实际上是sizeof(*指针)
,而sizeof指针,则是sizeof(指针)
。
所以sizeof(引用)
得到的都是代表该引用的指针,指针解引用后的值。
注意:认真理解以下代码的两行带有<等同于>的注释
#include <iostream>
using namespace std;
int main() {
#include <iostream>
using namespace std;
int main() {
int a = 10;
int& b = a; // 等同于 int* const d = &a; b = *d;
int* c = &a;
cout << "sizeof(b) = " << sizeof(b) << endl; // 输出 sizeof(b) = 4
//sizeof(b) 等同于 sizeof(*d) 但是实现sizeof(d)
cout << "sizeof(c) = " << sizeof(c) << endl; // 输出 sizeof(c) = 8
return 0;
}
}
结论
引用内部原理也是指针。
如果你要追根究底。引用这个地址,肯定是在内存里面占了空间了,不然这个地址信息放哪里。
但是,如果只是从程序的角度而言。
sizeof(指针)占用了空间,但是sizeof(引用)就没有占用空间,而是引用指向的对象的空间大小。这种情况认为没有占用空间。
比如,sizeof(指针)
,和sizeof(指针指向的对象)
,他们的大小会不一样。
但是sizeof(引用)
它的大小永远只有一个,那就是对象大小。
(其实是c/c++语言层面,做了这个限制导致的,引用在使用的时候默认被解引用了,这个时候sizeof只能取到指向的对象,而不是引用本身。)
浅出
不需要太过关注引用的内存问题。否则有钻牛角尖的嫌疑。
只需要知道引用与指针用法上的区别,各自擅长的领域,以及sizeof(引用)
输出值的原因,即可。
指针、引用相似点
引用和指针都可以指向基本类型。
引用是一个别名,它可以引用任何类型的对象,包括基本类型、自定义类型、指针等。
指针是一个变量,它可以存储任何类型的地址,包括基本类型、自定义类型、函数等。
既生瑜何生亮
在使用上:
指针需要使用*
和&
操作符来进行解引用和取地址操作,
引用则不需要。
指针可以为空,而引用不能。
另外,指针可以指向任何类型的对象,而引用只能指向与其类型相同的对象。
引用在定义时必须初始化,并且一旦初始化后,就不能被重新赋值。
指针可以。
首先,引用可以简化代码,使其更易读。因为引用是变量的别名,所以在使用引用时不需要使用*
和&
等符号,这使得代码更加简洁明了。(这一点有点类似java的引用)
其次,引用可以避免指针的空指针问题。指针可以为空,如果我们在使用空指针时没有进行判断,就会导致程序崩溃。而引用在定义时必须初始化,因此不存在空引用的问题。
另外,使用引用可以避免不必要的内存分配和拷贝。当我们传递一个对象时,如果使用指针,则需要在堆上动态分配内存,并在使用完毕后手动释放;如果使用引用,则不需要进行内存分配和释放,这可以提高程序的效率。
综上所述,当我们需要以传址方式传递参数、避免空指针问题、简化代码等场景时,使用引用可能更加方便和安全。至于是否分配空间的问题,不必纠结,容易进牛角尖。