在类中存储对对象的常量引用
Storing const reference to an object in class
这听起来像是一个基本问题,但我没有找到任何全面的答案,所以就在这里。请考虑以下代码片段:
struct A {
const std::string& s;
A(const std::string& s) : s(s) {}
};
int main() {
A a("abc");
std::cout << a.s << std::endl;
return 0;
}
演示。
据我了解,这就是UB。字符串文本"abc"绑定到构造函数中的const std::string&
,创建一个临时字符串对象。它也必然引用a.s
,一旦a
被构造出来,它就会被销毁。也就是说,常量引用不能链式延长寿命。晃来晃去的参考,轰隆隆。在这种特殊情况下,我在 ideone.com 上根本没有看到任何输出,但任何事情都可能发生(记住迅猛龙)。
好的,这个很清楚。但是,如果这实际上是我们的意图:我们想要存储对对象的常量引用呢?对现有的,而不是暂时的?这听起来像是一项非常自然的任务,但我只提出了一个(几乎)自然的解决方案。通过std::reference_wrapper
而不是引用接受构造函数的参数:
A(std::reference_wrapper<const std::string> r) : s(r) {}
由于std::reference_wrapper
从临时中删除了构造函数:
reference_wrapper( T&& x ) = delete;
这就像预期的那样工作。但是,这并不十分优雅。我能想到的另一种方法是接受转发引用T&&
并拒绝除带有 std::enable_if
的 const l 值字符串之外的所有内容。我认为这更不优雅。
还有其他方法吗?
UPD 另一个问题:这是std::reference_wrapper
的合法用法,还是被认为太具体了?
我会说自然的解决方案是做reference_wrapper
做的事情:防止临时施工:
struct A {
const std::string& s;
A(const std::string& s) : s(s) {}
A(std::string&&) = delete;
};
您还应该记住,默认情况下,具有引用类型的数据成员会使类不可分配(甚至无法进行移动赋值),并且通常很难实现赋值运算符。应考虑存储指针而不是引用:
struct A {
const std::string* s;
A(const std::string& s) : s(&s) {}
A(std::string&&) = delete;
};
Andrzej Krzemieński 在轻量级和方便的"显式"库中提供了一个非常简单的类lvalue_ref
,它以明确的意图解决了这个问题:
struct Processor
{
Big const& _big;
explicit Processor(lvalue_ref<const Big> b) : _big(b) {}
};
const Big b {};
Processor p {b}; // ok
Processor q {Big{}}; // error (temporary)
- 什么时候在C++中返回常量引用是个好主意
- 通过常量引用传递参数的矩阵模板类
- 在C++中使用非常量引用作为常量
- 具有常量引用参数的函数模板专用化
- 多个"常量引用"变量可以共享同一个内存吗?
- 为什么 STL 容器适配器堆栈中的 top 返回常量引用?
- 为什么常量方法可以采用非常量引用?
- 为什么当我们有常量引用时创建临时对象?
- 如何返回向量的常量引用?
- C++:常量引用参数
- 不同于按值传递和常量引用传递的程序集
- 为什么const_cast和static_cast常量引用没有效果?
- C++ 获取函数在常量引用中按值返回的结果
- 从 BubbleSort* 类型的右值初始化 'AssortedSorter&' 类型的非常量引用无效"
- C++ 在类中使用常量引用文本时 O2 内存泄漏
- 是否可以跨 dll 边界返回常量引用/指向 std::vectors?
- C++中大多数/所有 setter 函数的参数是否应该写为常量引用?
- 通过非常量引用参数修改常量引用参数
- 将常量引用传递给线程
- 为什么C++中没有常量引用,就像常量指针一样?