You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++中如何正确将变量以引用传入类?哪种实现更优?

C++中类持有外部变量引用的实现对比与选型

背景与示例代码

我想了解C中将变量作为引用传入类的最佳实现方式,目前知晓三种方法(C中可能存在更多),示例代码如下:

#include <string>
#include <iostream>

class Database {
    public:
        std::string name;
};

class ConsumeDatabase1 {
    public:
        ConsumeDatabase1(Database& database) : database_{database} {
            std::cout << &database << "\n";
        }
    private:
        Database& database_;
};

class ConsumeDatabase2 {
    public:
        ConsumeDatabase2(Database* database): database_{database} {
            std::cout << database << "\n";
        }

    private:
        Database* database_;
};

class ConsumeDatabase3 {
    public:
        ConsumeDatabase3(Database& database): database_{&database} {
            std::cout << &database << "\n";
        }

    private:
        Database* database_;
};

int main() {
    Database db;
    db.name = "Test";

    ConsumeDatabase1 db1{db};
    ConsumeDatabase2 db2{&db};
    ConsumeDatabase3 db3{db};
}

问题与解答

1. 第一种与第二种实现的区别是否为「第一种无法轻易传入nullptr,第二种允许传入nullptr」?

没错。第一种用非const左值引用作为构造参数,C++语法上不允许直接将nullptr绑定到引用,必须传入一个有效对象;第二种用指针作为参数,天然支持传入nullptr,意味着这个类需要处理database_为空的情况,否则会触发未定义行为。

2. 第一种与第三种本质相似,仅内部存储的是引用而非指针?

是的。两者的构造参数都是非const左值引用,保证传入的是有效对象,但内部存储分别用引用和指针:

  • ConsumeDatabase1直接存引用,引用一旦绑定就不能更改指向;
  • ConsumeDatabase3存指针,后续可以修改指针指向其他有效Database对象。

3. 不允许传入nullptr的场景下,第一种和第三种哪种更优?各自适用什么场景?

优先选第一种(存储引用)的场景:

  • 类的生命周期完全依赖于外部Database对象,且永远不需要切换指向:引用的语义是「必须绑定有效对象,且绑定后不可变更」,代码可读性更强,能明确告诉维护者:这个类的实例始终依赖同一个外部对象,不会中途切换。
  • 想避免空指针检查:引用本身不存在空的情况,代码里不需要额外判断database_是否有效,减少冗余逻辑。

选第三种(存储指针)的场景:

  • 类的实例在生命周期内需要切换指向不同的有效Database对象:引用无法重新绑定,而指针可以直接赋值为其他有效对象的地址,这种场景下必须用指针存储。
  • 需要兼容某些底层API或旧代码:如果类内部需要调用的函数接受指针参数,存储指针可以避免每次都用&database_取地址,减少代码冗余。

另外要注意:无论用哪种方式,都要确保外部Database对象的生命周期长于类实例的生命周期,否则会出现悬空引用/指针,触发未定义行为。


内容的提问来源于stack exchange,提问作者Chris_272

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 03:16:07