【问题标题】:How are values assigned to non-class types?如何将值分配给非类类型?
【发布时间】:2017-07-07 14:51:59
【问题描述】:

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

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

当我执行int p = x; 时,会不会像隐式复制构造函数那样简单地执行浅拷贝?所有其他隐式成员函数也是如此,因为在这些情况下,非类类型往往以与类类型相同的方式工作。

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

【问题讨论】:

  • 给自己买一个好的C++ book 并阅读它。那么如果你还有这样的基本问题,就来问吧。
  • @Walter 你怎么知道 OP 还没有读过并且可能还有这个问题?我认为这个问题根本不是基本问题。
  • 关于内置构造函数:stackoverflow.com/questions/5113365/…
  • 反问:如何区分int 的浅拷贝和深拷贝?
  • @Walter 你说的都不是真的。

标签: c++


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    如果指针和int等非类类型没有构造函数等成员函数,如何为它们赋值?

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

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

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

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

    【讨论】:

      【解决方案3】:

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

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

      分解你的代码:

      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,将该 RAM 初始化为值 2,并将分配的 RAM 的地址分配为 k 的堆栈地址处的值。

      【讨论】:

      • 您需要检查一些事实并使用正确的术语
      猜你喜欢
      • 2016-12-30
      • 1970-01-01
      • 1970-01-01
      • 2021-04-23
      • 1970-01-01
      • 2019-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多