这听起来像是一个基本问题,但是我没有找到任何全面的答案,所以就在这里。考虑以下代码片段:
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&
构造函数中,从而创建一个临时字符串对象。它也必须绑定到reference 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&&
并拒绝除const l值字符串之外的所有内容std::enable_if
。我认为,这甚至没有那么优雅。
还有其他方法吗?
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;
};
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句