防止将临时变量传递给 const 引用参数。

9

我有一个函数:

void AddImage(const Image &im);

这个函数不需要修改图像,但它会将图像存储为常量引用以供以后使用。因此,该函数不应允许临时变量。如果没有任何预防措施,以下内容将有效:

Image GetImage();

...

AddImage(GetImage());

有没有办法阻止这个函数调用?

1
除了立即问题外,还要考虑生命周期问题。在您当前的设计中,调用者负责确保图像的生存期与被调用方使用它的时间一样长。这种不对称的所有权可能会导致严重的问题。没有更多的上下文,我无法确定这是否是您代码中的情况。这绝对是需要仔细注意的事情。 - besc
这是绝对正确的。然而,这相当于工作系统的过度简化。在工作系统中,AddImage 是动画对象的成员函数,图像和动画对象的生命周期是同步的(它们通常是同一类的成员)。为了确保不会出现任何破坏顺序的问题,动画在销毁期间不检查其子元素。 - Cem Kalyoncu
1个回答

14

有几种机制可以防止将临时变量传递给const引用参数。

  1. 删除带有r-value参数的重载:void AddImage(const Image &&) = delete;

  2. 使用const指针:void AddImage(const Image*)。这种方法适用于C++11之前的版本。

  3. 使用reference wrapper:void AddImage(std::reference_wrapper<const Image>)

当使用支持C++11的编译器时,应首选第一种方法。它可以使意图更加明确。第二种方法需要运行时检查nullptr,并且不传达图像不能为空的想法。第三种方法可行且表达了意图,但过于显式。


1
现在我可以在编译时检测传递临时对象的问题了。非常感谢! - eudoxos
如果您能更详细地解释std::reference_wrapper在这种情况下的工作原理,我将不胜感激。如果参数是临时对象std::string,并且函数返回指向其.data()的指针,会发生什么?它在这种情况下能正常工作吗? - Kostiantyn Ponomarenko
我认为(不确定)第三个选项使用了一个带有右值重载删除的构造函数。因此,它将防止将临时对象作为引用传递。 - Cem Kalyoncu
请注意,如果您有多个const引用参数需要防止临时变量被传递,则选项1需要线性(或指数,如果您想避免歧义)多个重载。 - Edward Z. Yang
1
第三种方法“太显式”是什么意思? - Mark H
你写的代码对于这个任务来说太冗长了。 - Cem Kalyoncu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接