通过局部引用返回类字段引用的代码安全性探讨
代码安全性疑问
我认为以下代码是安全的:
class Clazz { public: Clazz() { holder_[0] = Test(42); } Test& bar() { return holder_[0]; } void foo() { const Test& t = bar(); std::cout << "t has val " << t.getVal() << std::endl; } private: std::map<int, Test> holder_; }; int main() { Clazz c; c.foo(); }
若bar函数采用如下实现方式,请问这段代码是否仍然安全?
Test& bar() { Test &t = holder_[0]; return t; }
两段代码其实是完全等价的,安全性没有任何变化,依然是安全的。
具体原因如下:
std::map的operator[]行为是明确的:如果键0已经存在于map中,它会返回对应Test对象的左值引用;如果不存在,则会默认构造一个Test实例插入map,再返回这个新对象的引用。- 你的代码里,
Clazz的构造函数已经通过holder_[0] = Test(42);完成了键0对应对象的初始化,所以后续调用bar()时,不管是直接返回holder_[0],还是先把这个引用赋值给临时变量t再返回,拿到的都是map中已存在的那个Test对象的有效引用。 foo函数里的const Test& t绑定的是map内存储的Test实例,这个实例的生命周期和Clazz对象c一致,不存在悬空引用的问题,程序可以正常输出预期结果。
简单说,修改后的bar只是多了一个中间引用变量,本质逻辑和原代码没有区别,引用有效性完全相同,代码依然安全。
内容的提问来源于stack exchange,提问作者Fernando
相关产品推荐
相关产品推荐

