c++ - 在类中存储对对象的 const 引用

标签 c++ c++11 pass-by-reference

这听起来像是一个基本问题,但我没有找到任何全面的答案,所以在这里。考虑以下代码片段:

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;
}

Demo .

据我所知,这是UB。字符串文字“abc”在构造函数中绑定(bind)到 const std::string&,创建一个临时字符串对象。它也被绑定(bind)到引用a.s,一旦a被构造,它就会被销毁。也就是说,const 引用不能链接生命周期延长。悬空引用,繁荣。在这种特殊情况下,我在 ideone.com 上根本看不到任何输出,但任何事情都可能发生(记住 velociraptors)。

好的,这个很清楚。但是,如果这实际上是我们的意图:我们想要存储对对象的 const 引用呢?对现有的,而不是临时的?这听起来像是一项非常自然的任务,但我只想出了一个(几乎)自然的解决方案。通过 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-value 字符串以外的所有内容。我认为这更不优雅。

还有其他方法吗?

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;
};

关于c++ - 在类中存储对对象的 const 引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35770357/

相关文章:

c++ - 关于摆脱样板代码的想法

c++ - auto&&和auto的区别

lua - 转换为 Lua 时实现 post/pre increment/decrement

c++ - 为什么我不能使用一些 GLFW 方法

c++ - 仅存在于 RAM 中的临时文件?

c++ - 获取 QGraphicsView 的可见矩形?

c++ - 使用可变参数包实例化函数模板

c++ - 跨 DLL 边界使用单例

javascript - 通过引用克隆对象的属性

php - 应用程序中的错误处理函数