r 值成员的用例 说明可能的选择

问题描述

我发现了一段有趣的代码,我想知道它是否是 UB?至少,根据 cppreference 不应该。使用 r 值引用是否有效?

可以通过绑定到 const 左值引用或右值引用来延长临时对象的生命周期...

this post 中讨论了类似的内容,但并未完全解决我的情况。

const res = await msRestNodeAuth.default.loginWithServicePrincipalSecretWithAuthResponse(_clientId,_secretValue,_tennantId);

const client = new armResources.default.ResourceManagementClient(res.credentials,_subscriptionId);

const resourceGroups = await client.resourceGroups.list();

解决方法

TL;DR:这不会按照您希望的方式工作。不过,它可能不会是 UB,只要 instance_ 引用的内容足够长以支持来自 operator=(...)load(...) 调用。

说明

任何类型的引用,无论是右值还是左值,一旦初始化就不能被重新绑定,也不能保持未初始化状态。从根本上说,您在这里想要的不能使用引用。

静态 instance_ 必须在程序启动时已经初始化为某个值,这将使得:

instance_ = std::move(instance);

赋值给 instance_ 最初引用的对象,这意味着这对 operator= 使用赋值运算符 ServiceLocator<T>,而不是重新绑定引用。

即使它可以工作,RValues 也只能将生命周期延长到它初始化的自然范围(就像它们是对象值一样),并且只能在用 初始化时延长生命周期>真正的临时对象(例如 PR 值,例如 T() 表达式或返回按值对象的函数的结果)。

因此,即使可以重新绑定,此扩展也不会适用,因为参数不会产生临时表达式。

可能的选择

如果您想为不可移动/不可复制的对象创建定位器,可以考虑使用 std::optionalstd::unique_ptr 以允许空状态,并提供 {{1 }}-like 函数来就地构造它。如:

emplace

或者,更好的是,不要使用资源定位器。他们只是伪装成抽象的单身人士,但他们同样邪恶。