如何将值分配给非类类型

How are values assigned to non-class types?

本文关键字:类型 分配      更新时间:2023-10-16

如果非类类型(如指针和 int)没有像构造函数这样的成员函数,那么如何为它们赋值? 例如:

int x = 1;
int p = x;
p = 2;
int a = int();

当我这样做时int p = x;会只是执行浅层复制,就像隐式复制构造函数一样吗?所有其他隐式成员函数也是如此,因为在这些情况下,非类类型的工作方式往往与类类型的工作方式相同。

此外,当你有一个类时,该类可能有一个存储某个值的对象(如果该类应该表示一个值),但是这些非类类型是否有某种缓冲区?否则,如何将值从一个复制到另一个值?

为了更好地理解内置类型的语义,请考虑C++语言的设计和演变。

最初没有C++,只有C。在 C 中,没有类,只有内置类型 - 例如ints、floats、指针等。变量的每个定义都意味着以某种方式分配了足以存储此类变量的空间(该分配可以是保留的实际内存,也可以只是 CPU 寄存器的名称)。稍后,对此变量的所有访问都将路由到指定的空间。根本不存在构造函数或析构函数,将一个变量复制到另一个变量只是意味着将源"空间"的内容复制到目标中。

后来,当引入C++时,付出了巨大的努力,使遗留的C程序尽可能与新语言兼容。这意味着,对于内置类型,行为与 C 中的行为完全相同。它仍然仍然是事实。每当您定义内置类型的变量(优化器不会对其进行优化,因为它可以)时,都会为其分配一个空间,并且所有访问都将路由到此空间。复制这些类型始终是从目标到源的直接空间复制。

如果非类类型(如指针和 int)没有像构造函数这样的成员函数,那么如何为它们赋值?

构造函数不是魔法。编译器和计算机不会因为类型没有构造函数的概念而随机发现自己无法执行基本的内存复制操作。

内部逻辑类似,但复制操作更简单。复制构造函数是一种对类成员(类本身可能是其他类实例或内置类型)执行操作的方法。内置类型是"基本情况",我可以向您保证,编译器知道如何生成代码来复制它们。

当然,因为它们是"基本情况",所以在这里没有有意义的应用术语"浅拷贝"和"深拷贝"——副本就是副本就是副本。int没有可以复制或不复制的间接资源,这就是浅/深复制与类和指针的用武之地。

对编译器工作原理的更深入分析超出了范围。

在C++基元类型中,(bool, char, short, int, long, double, float) 是可以直接存储在 CPU 寄存器中的值。

当 CPU 到达变量的声明时,它会获取 RAM 来存储值。在 C++11 及更高版本中,将执行值初始化的附加步骤。

要分解代码,请执行以下操作:

int x = 1;

这将为一个 int(通常为 4 个字节)获取足够的 RAM,将符号 x 与所获取的 RAM 的地址相关联,并为该地址的 RAM 分配值 1。

int p = x;

这将为另一个 int 获取足够的 RAM,将其与符号 p 关联,并将存储在与符号 x 关联的地址的值复制到新地址的 RAM 中。

p = 2;

这将转到与符号 p 关联的 RAM 地址,并用 2 覆盖那里的值。

int a = int();

这将获取另一个 int 大小的 RAM,将 RAM 的地址与 a 相关联,调用无参数 int 转换函数,并将返回值 (0) 分配给 a 地址处的 RAM。

输入指针

为了更深入地了解底层机制,C++ RAM 中的两个位置为变量分配内存:堆栈和堆。 当您使用语法int g;声明变量时,关联的 ram 是一个堆栈地址,并在输入声明变量的作用域(由{}分隔的代码段)时使用,并保持分配状态,直到退出作用域,此时它被解除分配。

指针的操作类似: 如果您声明

int* k;

指针的空间在堆栈上分配,地址处的值要么是垃圾,要么是 C++11 值初始化为 null。若要将对象分配给指针,请使用new运算符,

k = new int(2)

它分配足够的堆 RAM 来容纳一个 int,用值 2 初始化该 RAM,并将分配的 RAM 的地址分配为堆栈地址 k 处的值。