static成员

static成员分为static成员变量和static成员函数,它们属于类而非某个具体的对象。

static成员变量

  • 必须在类外定义并初始化,形式为类型 类名::变量名 = 初值
  • 所有对象共享同一份数据,生命周期从程序开始到结束。
  • 可通过类名直接访问(类名::变量名),也可通过对象访问。
class Example {
public:
    static int count; // 声明
};
int Example::count = 0; // 定义并初始化

static成员函数

  • 只能访问static成员变量,不能访问非static成员。
  • 无this指针,因此不能调用非static成员函数。
  • 可通过类名直接调用(类名::函数名())。
class Example {
public:
    static void printCount() { 
        cout << count; // 仅能访问static成员
    }
};


友元类

友元类(friend class)允许一个类访问另一个类的私有成员。

  • 友元关系是单向的,不具有传递性。
  • 通常在类定义中声明友元类,形式为friend class 类名;
class A {
private:
    int secret;
    friend class B; // B可访问A的私有成员
};

class B {
public:
    void showA(A& a) {
        cout << a.secret; // 直接访问A的私有成员
    }
};


内部类

内部类是定义在另一个类内部的类,与外部类相互独立。

  • 内部类可以访问外部类的static成员和私有成员(需通过对象或指针)。
  • 内部类的作用域受外部类限制,需通过外部类名::内部类名访问。
class Outer {
private:
    static int x;
    int y;
public:
    class Inner {
    public:
        void print(Outer& o) {
            cout << x;      // 直接访问static成员
            cout << o.y;    // 通过对象访问非static成员
        }
    };
};
int Outer::x = 10;


匿名对象

匿名对象是未被命名的临时对象,生命周期仅限当前行。

  • 常用于简化代码,如直接调用成员函数或作为函数参数。
  • 语法形式为类名(参数)
class Temp {
public:
    void show() { cout << "Hello"; }
};

int main() {
    Temp().show(); // 匿名对象调用后立即销毁
    return 0;
}


对象拷贝的编译器优化

编译器在特定场景下会优化对象拷贝,减少不必要的构造和析构。

常见优化场景

  1. 返回值优化(RVO)
    函数返回局部对象时,编译器可能直接构造到调用者的目标位置,避免临时对象拷贝。

  2. 命名返回值优化(NRVO)
    类似RVO,但针对已命名的局部变量。

  3. 临时对象优化
    临时对象作为参数传递时,可能直接绑定到引用或目标对象。

示例对比

class Test {
public:
    Test() { cout << "构造"; }
    Test(const Test&) { cout << "拷贝"; }
};

Test func() {
    Test t;
    return t; // 可能被优化为直接构造到调用处(NRVO)
}

int main() {
    Test t = func(); // 若无优化:构造+拷贝;优化后:仅构造
    return 0;
}

禁用优化
可通过编译选项-fno-elide-constructors(GCC/Clang)关闭优化,观察完整拷贝过程。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐