引用到底有没有内存的分配?
引用分配有内存,相当于常指针.在分析程序时,应按没有分配内存理解.在画内存图解时,应画出引用的地址.所以引用必须被初始化,指针不必。
有了 malloc/free 为什么还要 new/delete ?
malloc 与 free 是 C++/C 语言的标准库函数,new/delete 是 C++的运算符。它们都可用于申请动态内存和释放内存。 对于非内部数据类型的对象而言,光用 malloc/free 无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free 是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于 malloc/free。 因此 C++语言需要一个能完成动态内存分配和初始化工作的运算符 new,以及一个能完成清理与释放内存工作的运算符 delete。注意 new/delete 不是库函数。
全局静态变量?
静态存储区分配内存单元,未经初始化的全局静态变量会被程序自动初始化为0,所谓初始化应如下,其他报错。
class A
{
public:
static int a;
};
int A::a;
void main()
{
cout<<A::a<<endl;
system("pause");
}
引用的VS底层实现
#include<iostream>
using namespace std;
int main()
{
int x=1;
int &b=x;
return 0;
}
//反汇编
9: int x = 1; //源代码
00401048 mov dword ptr [ebp-4],1 //反汇编代码
10: int &b = x; //源代码
0040104F lea eax,[ebp-4] //反汇编代码
00401052 mov dword ptr [ebp-8],eax//反汇编代码
mov dword ptr [ebp-4],1 //把1赋值给ebp(栈底指针)-4的地址
lea eax,[ebp-4] //把ebp-4的地址赋值给寄存器eax
mov dword ptr [ebp-8],eax //把寄存器eax里的值赋值给ebp-8的这块地址
上述三行代码的作用就是将1赋值给x,然后将x的地址赋值给了引用b。
而在内存中,它是这样的:
所以,引用占用内存空间,引用的本质就是所引用对象的地址。写过一段代码来测试引用的地址,发现引用的地址和变量的地址是一样的。事实上,是因为b的地址我们没法通过&b获得,因为编译器会将&b解释为:&(*b) =&x ,所以&b将得到&x。也验证了对所有的b的操作,和对x的操作等同。
智能指针
auto_ptr在赋值时会转移内存空间所有权,会导致程序崩溃,已弃用,C++11用unique_ptr。
shared_ptr是多个智能指针共享一块内存区域,通过引用计数实现内存的new和delete,但存在一个问题会造成死锁,所以有一个weak_ptr存在,防止该问题。
常量
对于局部常量,通常位于栈区,而对于全局常量,编译器一般不分配内存,放在符号表以提高效率。字面量一般位于常量区。
constexpr
只读”不就意味着其不能被修改吗?答案是否定的,“只读”和“不允许被修改”之间并没有必然的联系, const 修饰了 con_b 变量,表示该变量“只读”,即无法通过变量自身去修改自己的值。但这并不意味着 con_b 的值不能借助其它变量间接改变,通过改变 a 的值就可以使 con_b 的值发生变化。同理,底层const指针表示只读指针指向的变量,但不意味着其变量值不能借助其他指针改变。传统const的问题在于“双重语义”,既有“只读”的含义,又有“常量”(不可改变)的含义,而constexpr严格定义了常量。
虚函数是如何实现运行时多态的
子类通过重写父类的虚函数,那么虚函数表中原来父函数地址会被替换,通过该机制实现运行时多态。