让我们看以下函数声明:
void print(SomeType const* i);
在这里,参数i的const*
特性表明了意图,即该参数是可选的,因为它可能为nullptr
。如果这不是预期的,那么参数将是一个const&
。显然,使用指针来传达可选语义并不是设计指针时最初的意图,但长期以来这种用法一直很有效。
现在,在现代C++中通常不建议使用原始指针(应该避免使用它们,而改用std::unique_ptr
和std::shared_ptr
来精确地指示特定的所有权语义),我想知道如何正确地指示函数参数的可选语义,而不需要通过值进行传递,即复制,例如
void print(std::optional<SomeType> i);
经过一段时间的思考,我想到了使用:
would do.
void print(std::optional<SomeType const&> i);
实际上这是最精确的。但事实证明,std::optional
不能使用引用类型。¹
此外,使用
void print(std::optional<SomeType> const& i);
如果这样做,并要求在调用方的 std :: optional 上存在我们的 SomeType
,那么将绝不是最佳选择,这可能需要在那里复制。
问题:那么允许可选参数而不复制的好的现代方法是什么?在现代C ++中,在这里使用原始指针仍然是合理的方法吗?
¹:具有讽刺意味的是,描绘为什么 std :: optional
不能具有引用类型的原因(关于重新绑定或传递赋值的争议)在 const 参考文献的 std :: optional
的情况下不适用,因为它们无法分配给。
optional< reference_wrapper<T> >
。 - underscore_doperator=(...) const
,语言中没有任何阻止它的东西,尽管好的习惯应该是如此 :-) 但是即使忽略这一点,您也面临与非const引用相同的问题,重新绑定将与基于值的可选项发生的情况不一致,因此可能会令许多用户感到惊讶。 - Arthur Taccastd::shared_ptr
而不是std::smart_ptr
? - David Zstd::optional<std::cref<SomeType>>
,但是我会只使用可选参数的SomeType*
。 - Mooing Duckstd::optional<std::reference_wrapper<const SomeType>>
。而std::cref
只是一个辅助函数。 - Reizo