繁体   English   中英

C++编译器访问静态成员和访问普通成员的方式有什么区别?

[英]C++ What's the difference between the way compiler accesses static members and accesses ordinary members?

假设我设计了一个这样的类:

// MyClass.h
#pragma once

class MyClass
{
public:
    const int member = 1; // Since it is a const-integral type var...
    static const int s_member;
    ...
};

然后我可以像这样访问每个成员:

// MyClass.cpp
const int MyClass::s_member = 2; // Initialization of a static member
int main()
{
    MyClass* myClass = new MyClass;
    std::cout << "access to an ordinary member : " << myClass->member << " OR " << (*myClass).member << std::endl;
    std::cout << "access to a static member : " << MyClass::s_member << std::endl;
    
    ...

    return 0;
}

(据我所知,通过指针访问类成员只会产生细微的差别:传递地址并取消引用它。)

在这里,我很好奇的是这与编译器访问静态成员的方式之间的区别。

我已经知道静态成员的内存位于类实例之外的某个地方,而不是内部。 (因此每个类实例为其静态成员使用相同的内存。)

那么,访问静态访问的唯一区别是“从哪里访问”? 还是存在超越它的东西?

首先,您应该意识到整数类型的const static成员通常根本不涉及任何内存访问。 除非您以(或多或少)强制编译器这样做(例如,获取其地址)的方式使用它,否则这通常(通常?)只是常量的符号名称。 所以,给定类似的东西:

class foo {
    static const int bar = 1234;
public:
    void baz() { 
        for (int i=0; i<bar; i++)
            // ...
   }
};

...您通常可以期望您的i<bar比较结果是这样的:

cmp rcx, 1234

...根本没有尝试访问任何变量。

非常量static成员基本上是一个具有一种有趣名称的全局变量。 因此,在链接时,有趣的名称(即类名和变量名本身的组合)将被修改(或“装饰”,用 MS 来说)为变量生成一个唯一的名称,它将像任何其他全局变量一样分配。 因此,半代表性代码可能如下所示:

mov rax, foo$$bar
cmp rcx, rax

非静态变量是基于每个对象分配的。 当调用成员函数时,它接收this作为“隐藏”参数。 在函数内部,它可以通过添加适当的偏移量来访问变量,并取消引用结果以获得指定的变量。

在此处输入图片说明

对于单继承计算正确的偏移量非常简单,但在虚拟多重继承之类的情况下可能会变得更加复杂。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM