这听起来像是一个基本问题,但是我没有找到任何全面的答案,所以就在这里。考虑以下代码片段:
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 reference不能链接生命周期延长。悬空引用,繁荣。在这种情况下,我在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值字符串之外的所有内容。我认为,这甚至没有那么优雅。还有其他方法吗?
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/