c++ 防止通过引用 Package 将引用返回到堆栈

plupiseo  于 2023-01-22  发布在  其他
关注(0)|答案(1)|浏览(104)

我正在处理一个容器,它的下标操作符返回一个 Package 器引用,如下所示:

my_container::reference my_container::operator[](std::size_t i);

容器的内部元素表示不能被直接引用,需要代理对象,引用本身删除了复制和移动构造函数,所有操作只针对右值引用定义。
但是,通过autodecltype(auto)推导 Package 器对象时会出现问题。例如,在以下代码中:

my_container bar();
auto foo(std::size_t i)
{
    my_container c = bar();
    return c[i];
}

auto推导到my_container::reference而不是my_container::value_type,因为引用代理是一个对象类型,并且RVO保证没有复制或移动构造函数被调用,这是一个问题,因为在上面的代码中返回了堆栈引用。
有没有办法防止这样的行为?据我所知,没有办法绕过RVO,但也许我错过了一些东西。
编辑:为了给予更多的上下文,容器是一个整数向量上的位掩码。对元素的任何赋值都必须屏蔽赋值,这就是为什么需要代理引用。

d6kp6zgx

d6kp6zgx1#

C++不是一种安全的语言。
虽然聪明和一致地使用某些语言机制可以使语言安全-er,但语言本身有许多构造,如果不进行实质性的语言更改,它们就不会安全。悬空引用问题是最大的问题之一。
你不能通过使用语言内机制来完全解决悬空引用问题,任何这样做的尝试都会遇到两个棘手的问题:
1.解决方案不会是完整的。会有一些方法可以绕过它,而且通常不会主动恶意(即:某些人可以在没有明确尝试的情况下完成它们)。
1.该解决方案将使该类型的某些合法用途无法实现。
后一个很重要,通过设置“所有操作都只为右值引用定义”,你就阻止了像这样简单的操作:

for(auto &&ref : bool_vector)
  ref == true;

用户必须输入std::move(ref) == true;,虽然你的类型可能会满足indirectly_writable的定义,用户会期望能够得到一个语言引用到你的proxy-reference,并使用它作为一个实际的 reference 到一个值,也就是说,他们会期望*it = val;auto &&ref = *it; ref = val;是同样有效的。
当他们的合法代码不能被编译时,他们会很不高兴,所以在试图提供一些安全性的时候,你已经让你的类型对你的用户来说不那么“可用”了。
在任何情况下,您的特定问题都是#1:您无法在语言中提供这种形式的安全性。您无法创建提供这种形式的安全性的代理迭代器。保证省略是 * 保证 * 的,并且任何执行return prvalue_expression;auto返回函数将 * 总是 * 工作,无论prvalue_expression类型的任何属性如何。

相关问题