const 引用函数参数:是不是可以禁止临时对象?

Posted

技术标签:

【中文标题】const 引用函数参数:是不是可以禁止临时对象?【英文标题】:const reference function parameter: Is it possible to disallow temporary objects?const 引用函数参数:是否可以禁止临时对象? 【发布时间】:2018-10-17 02:50:44 【问题描述】:

可以有一个强制执行以下语义的函数参数:

参数不会被函数改变。 调用函数永远不会为参数创建副本或临时对象。

例子:

void f(const std::string & str);

接口告诉客户端参数不会被改变,如果参数已经是std::string类型,则不会创建副本。

不过还是可以这样称呼

const char * hello = "hello";
f(hello);

在进入函数 f 之前创建一个临时 std::string 对象,并在退出 f 后再次销毁它。

是否可以通过不同的函数声明或(假设)更改 std::string 实现来禁止这种情况。

【问题讨论】:

对我来说听起来像是 XY 问题。该语言的优点之一是自动临时创建和绑定。你为什么要禁止这个?如果您关心由于调用构造函数而可能导致的性能下降,那应该不是 API 提供者的问题,而是调用者的问题。 std::string 的实际解决方案是使用 std::string_view 或自制解决方案。 必须查一下 xy-problem 是什么意思。不,我不这么认为。同意这将是客户的责任。但这也是我,我很好奇我是否可以确保我不会在我的电话中犯错误。 std::string 在这里仅用作示例。对 std::string 不是特别感兴趣。一件好事是我学到了一些关于 =delete 的新知识。 【参考方案1】:

我要在这里从头开始。

或通过(假设)更改std::string 实现

不要这样做,因为害怕鼻恶魔。说真的,不要。让标准库以标准方式运行。

是否可以通过不同的函数声明来禁止这一点

事实上,另一个声明只是门票。添加一个接受右值引用的重载,并将其定义为已删除:

void f(std::string && str) = delete;

重载解析会临时选择它,删除的定义会导致错误。您的预期函数现在只能使用左值调用。

【讨论】:

std::string 只是一个大家都知道的例子,我同意我不想改变它。 delete 关键字很有趣,我必须尝试一下。我只知道以这种方式删除默认构造函数等。 @LudwigSchulze - 您可以为任何函数提供已删除的定义。当您想防止某些事情时,更容易使重载解决方案蓬勃发展:) 我觉得在尝试了这个之后,我可能会对有~5个参数的情况有一个后续问题,其中~3个参数具有这种语义。当然,这将是一个新问题。

以上是关于const 引用函数参数:是不是可以禁止临时对象?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在通过 const 引用传递临时值时调用复制构造函数?

为什么赋值操作符函数的参数为const引用,返回值为引用

为啥当我们有 const 引用时创建临时对象?

临时变量不能作为非const引用

为啥非常量引用不能绑定到临时对象?

const用法