C 成员变量语义

C++ member variable semantics

本文关键字:语义 变量 成员      更新时间:2023-10-16

我有一个相当简单的问题,上面有一个关于答案的信息。

我广泛的问题:当您声明成员变量(无论是公共还是私有)以及可变类型的所有排列时,例如静态与常规变量?

class some_class
{
private:
    static const std::string str;
public:
...
}

我已经意识到,在C 中,没有一个不可变化的概念,也就是说,是一个非构造变量,因为我被教导相信存在着像Java这样的语言。Java中也可能是如此,但是这不是我被教导想到事情的方式,因此我想提出正确的方式来思考这些非发明变量。

public class main {
    public static void main(String[] args) {
        String str; // A kind of non-variable, or non-constructed variable (refers to null).
        str = new String(); // Now this variable actually refers to an object rather than null, it is a constructed variable.
    }
}

由于C 允许您通过initializer列表在构造函数中初始化成员变量,而且我通过使用调试器向我自己证明了该变量在通过初始化器列表初始化之前不存在该变量(默认情况下或默认情况下)),那么,当您声明成员变量时,实际上是在幕后进行的?

棘手的问题 - 取决于视角。/p>

从伪机器的角度来看,通常在类中添加非静态的普通旧数据类型会使该类型类型更大。编译器还弄清楚了如何对齐它和相对内存偏移以解决结果机器代码中的对象。

中的对象。

这是伪机级别,因为在机器级别上,数据类型实际上并不存在:只有原始位和字节,寄存器,指令,类似的内容。

当您添加非重要用户定义类型时,此递归,编译器生成了访问会员成员等的说明。

从较高的级别上,将成员添加到类中,使成员可以从类的实例(对象)访问。构造函数初始化了这些成员,而破坏者会摧毁它们(递归触发具有非平凡破坏者的成员的破坏者,以及在施工阶段的构造函数的同样)。

>

但是您的示例是静态成员。对于静态成员,它们存储在机器级别的数据段中,并且编译器生成代码以从数据段访问这些静态成员。

其中一些可能有些混乱。C 与C是硬件级语言的C分享其遗产,其静态汇编和链接会影响其设计。因此,尽管它可以非常高级,但它的许多结构仍然与硬件,编译器和链接器的工作方式相关,而在Java中,该语言可以做出一些更明智的选择,以支持程序员便利,而没有语言设计在某种程度上反映了所有这些东西。

是,否。

Java中类类型的变量是确实是一个指针。与C和C 指针不同,它不支持指针算术(但这对于作为指针并不重要 - 例如,Pascal中的指针也不支持算术)。

因此,当您定义Java中的类类型的变量:String str;时,它几乎等同于在C 中定义指针:String *str;。然后,您可以为您分配一个新的(或现有)字符串对象,如您所示。

现在,通过使用指针(或参考)明确地,可以在C 中实现C 的效果大致相同的效果。虽然有差异。如果使用指针,则必须明确地解除该指针以获取所指的对象。如果您使用引用,则必须必须初始化参考文献 - 一旦您进行了参考,该引用将永远无法引用以外的任何对象。

C 中的const变量也有一些特殊规则。在许多情况下,您只是定义一个值的符号名称:

static const int size = 1234;

...并且您永远不会以需要它具有地址的方式使用该变量(例如,采用其地址),通常根本不会分配一个地址。换句话说,编译器将知道您与该名称相关联的值,但是当编译完成后,编译器将替换您使用该名称的任何地方的值,因此变量(因此)基本上消失了(尽管如果您的编译器生成调试信息,则通常会保留足够多的信息,以了解并正确显示其名称/类型)。

c 确实有一种情况,其中变量是 little ,就像一个被声明但未初始化的java" zombie"对象。如果您从一个对象移动:object x = std::move(y);,则移动完成后,移动的来源(在这种情况下为y)可能处于相当奇怪的状态,但是 abion abion abion 它是为其分配新值的。例如,在字符串的情况下,它可能是一个空字符串 - 但它也可以准确保留其移动前的值,或者它可以包含一些其他值(例如,目标字符串在移动前保持的值)。

即使如此,即使您不知道它的状态,它仍然是一个应该维护其班级的不变性的对象 - 如果您从字符串移动,然后要求字符串的长度,该长度应与字符串实际包含的内容匹配 - 例如,如果(例如)您打印出来,您不知道字符串会打印出来,但是您如果不是等于NullPointerException - 如果是一个空字符串,则不会打印出任何内容。如果是一个非空字符串,则打印出的数据的长度应与其.size()指示的内容相匹配,依此类推。

另一种明显相似的C 类型将是指针。非初始化的指针不能指向对象。指针本身存在 - 它只是没有指的。试图取消它可以给您某种错误消息,告诉您您已经尝试使用无效指针 - 但是除非它具有静态存储持续时间,否则您已经明确初始化了它,就无法保证它将是一个null指针都可以 - 取消指示它可以给出垃圾价值,抛出例外或几乎其他任何东西(即,它是未定义的行为)。