返回值的初始化应忽略自动对象的恒常性
Initialization of a return value should ignore constness of automatic object
坚持常量的正确性,您可能希望将类型unique_ptr
的本地对象设置为常量,如下所示,而T
在这里是一些不重要的类型:
unique_ptr<T> foo() {
const unique_ptr<T> p = make_unique<T>(...);
... using p's pointee ...
return p;
}
不幸的是,它无法编译,因为返回值无法初始化,因为unique_ptr
没有复制构造函数,并且移动构造函数不可行,因为p
是常量。
如果C++标准会说当 return 语句的"操作数"是一个自动对象时,那么它的潜在恒常性将被忽略呢?初始化返回值后无法引用自动对象,因此其恒常性现在无关紧要。在其析构函数中,const 对象也可以修改,因此它实际上只是关于定义常量结束的位置:就在析构函数之前或在此特殊情况下在返回值的构造函数之前。
然而,"不能引用"并不是全部事实:在初始化返回值后排序的其他局部变量的析构函数可能会引用它。但我认为他们不可能关心 const 对象被修改了。他们通过指针或对 const 的引用来了解对象,即从他们的角度来看,他们只知道他们不允许修改它,他们无法知道其他人是否被允许修改它。
您认为对C++标准进行这样的更改是个好主意吗?或者您是否在我下面给出的解决方案之外看到其他解决方案?
仅供记录:非解决方案和其他解决方案:
- 你不能
return unique_ptr<T>(p.get())
,因为现在你有两个unique_ptr
,每个都认为它是唯一的所有者。 - 您无法
return unique_ptr<T>(p.release())
,因为p
是常量,而release()
是非常量成员方法。 -
return move(p)
没有用,因为它不会删除恒常性,因此仍然无法调用移动构造函数。 - 编辑:正如Chris Beck指出的那样,
return const_cast<unique_ptr<T>&&>(p)
也不是解决方案,因为修改const对象是未定义的行为(标准N4140中的7.1.6.1 p4(。
由于 unique_ptr 是仅移动类型,因此按值返回将(假设(调用返回值的移动构造函数。但是由于从中移动是一种破坏性操作,因此您无法真正从 const 对象中移动。
但我认为 C++17 的"保证复制省略"(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0135r0.html(会对此有所帮助。基本上,这将允许从函数(例如 const unique_ptr(按值返回不可移动的类型。再一次,我担心,你将不得不等待新标准
我认为这样的更改将是一个坏主意。我有点明白你来自哪里,但你对你的问题的解决方案只会创造一个目前已经解决的新问题。
我认为我们需要考虑为什么我们一开始就const
对象。
它关乎安全性,并确保给定变量不会发生错误的事情。通过制作unique_ptr
const
,您实际上是在说您不希望在对象上发生任何所有权操纵。您仍然可以操作它管理的对象:
std::unique_ptr<T> foo()
{
// const object means no calling non-const member functions
// which means no changing the ownership of the managed pointer
const std::unique_ptr<int> p = std::make_unique<int>();
// but we still get to manipulate the thing being pointed to:
*p = 6;
return std::move(p); // compile error - changing ownership
}
在这种情况下,您可能希望进行unique_ptr
const
以防止意外退回,而不是您想要返回的其他unique_ptr
。将unique_ptr
const 设置为常量实际上可以防止它被错误地返回。因此,我们现在能做的是使我们所有的unique_ptr
对象都const
除了我们希望将其所有权归还给调用方的对象。
您的更改将使该保护无效,并且一开始就使对象const
的意义会降低。
- 如何实现自定义匹配器以检查 Catch2 中的对象相等性
- const_cast静态数组以添加恒常性
- 自动模板参数、数据成员和恒常性
- 有没有办法检测自身内部的类恒常性?
- 为什么const_cast删除指针的恒常性,而不删除指向常量的指针的恒常性?
- 对指针和恒常性兼容性的引用
- 自定义容器中的括号运算符中的恒常性
- C++ 重载分辨率和恒常性
- C++17类模板演绎常性
- C++ 函数匹配和恒常性
- 如何忽略函数模板中的恒常性?
- 常量自动和对象恒常性
- 比较运算符 == 中的共享指针恒常性
- 添加额外的恒常性会导致编译器错误
- 删除模板化函数中的恒常性
- 无法正确理解我的恒常性
- 模板转换运算符优先级和恒常性
- const_iterator和恒常性const_iterator::value_type
- 使用const_cast来添加恒常性 - 坏主意?
- 返回值的初始化应忽略自动对象的恒常性