声明静态对象和指向静态对象的指针之间的区别

Difference between declaring static object and pointer to static object

    #include <iostream>
    using namespace std;
    class First{
        public:
        void fun()
        {
            cout<<"base fun called\n";
        }
    };

    class Second{
        public:
        static First x; //Line 1
        static First *y; //Line 2
    };

    First Second::x; //Line 3

    First* Second::y; //Line 4

    int main()
    {
        Second::x.fun();
        Second::y->fun();
        return 0;
    }

第 1 行和第 2 行是声明,第 3 行和第 4 行是定义,这是我从其他一些关于静态成员的 Whosebug 帖子中了解到的。

Q1。为什么我们必须这样定义静态对象? (第 3 行和第 4 行)

Q2。 x 和 y 有什么区别?(第 1 行和第 2 行)

Q3。为 x 和 y 对象分配的内存在哪里?(第 3 行和第 4 行)

您的 y 是一个 pointer(不是对象 - 指针与它可能指向的对象不同)。因为它是 static,所以它用 nullptr 初始化,除非你 明确地 定义它初始化为其他东西(例如有一些 First z; 对象并定义First* Second::y= &z;)。 所以 Second::y->fun(); 正在取消引用空指针,即 undefined behavior. You really should be very scared.

我们无法在这里回答您的所有问题(需要整本书,指针的概念及其 semantics is difficult to explain, and related to pointer aliasing; read also about virtual address space). So take a few weeks to read some good book like Programming - Principles and Practice Using C++; you probably will benefit by also reading SICP & Introduction to Algorithms (even if neither is about C++; however both are related to programming, which is difficult to learn)。

又见一些不错的C++ reference site, it gives a short explanation about static class members.

请注意,在真正的 C++11 中,使用原始指针通常(但不总是)是一种难闻的气味。你可能应该考虑 smart pointers,但是 YMMV.

Q1 当您编写 class 语句时,它通常是声明。任何地方都没有分配实际的数据成员。对于非静态成员,定义发生在实例化时,即调用构造函数时。 但是,静态成员与实例化无关。它们应该被分配一次,你应该决定在哪里。这就是实际定义的原因。该文件(编译时)将负责实际分配这些成员。

这实际上也回答了 Q3。至于Q2,我不确定具体问题是什么

1) 因为当创建 class 的对象时,不会为它们的静态成员分配内存 - 所以第 1 行和第 2 行 声明 应该有这样的成员,但是第 3 和 4 行 定义了 应该分配内存的位置。

2) 字面上没有太大区别 - xy 都只是 class Second 的成员,但类型不同。 x 属于 First 类型,其大小等于 First 个成员的总和。 y 属于 First* 类型 - 它的大小取决于特定编译器中使用的指针的大小。

3) 已经有一个good answer about memory allocation for static members. The most common implementation is to use data segment的程序。