【问题标题】:avoid copy by value when initializing reference初始化引用时避免按值复制
【发布时间】:2011-08-14 05:14:41
【问题描述】:

我有一个函数接口:

struct iFace {
  virtual Type& getType() = 0;
}

我们的想法是像这样检索它:

iFace& iface = getIface();
Type& type = iface.getType();

但是,我偶尔会犯错误并写:

Type type = iface.getType();

按值复制,这​​是我想要避免的。但是,当我犯这样的错误时,编译器不会发出警告,因为它的语法是合法的。我想为此触发一个编译时错误,问题我的替代方案是什么?

我考虑过声明一个复制构造函数但没有在任何地方定义它,如果使用它会导致链接时错误,但是我将无法在 ANY 情况下使用复制构造函数,这不太理想

【问题讨论】:

  • 你不能同时拥有它。
  • 这就是我害怕的,所以我想在这里问它来确认。感谢您的确认
  • 这取决于类型是什么。如果你可以将 Type 抽象化,那么你将无法创建实例。

标签: c++ default-copy-constructor return-by-reference


【解决方案1】:

通过将复制构造函数和赋值运算符置于“私有”下,使 iFace 不可复制。然后提供一个显式的 Copy 方法。

class Type {
public:
  virtual Copy(Type& dest) = 0;
private:
  Type (const Type &) {assert(false)}
  Type & operator=(const Type &)  {assert(false)}
}

您也可以使用boost noncopyable 来做同样的事情(其实现如上)。

所以如果你想复制你的代码,你会这样做

Type& type = iface.getType();
Type typeCpy;
type.Copy(typeCpy);

顺便说一句——我要补充一点,如果您出于性能考虑而这样做,您确定优化器不会为您删除临时副本吗?

【讨论】:

  • 这属于复制构造函数变得不那么可用的情况。让我们把它作为计划“如果一切都失败了”
  • @lurscher,您也可以提供明确的副本,请参阅我的编辑。
  • 我们可以使用显式关键字来限制复制构造函数吗?
  • 我不确定优化器是否做了任何相关的优化。我只关心以最简洁的方式编写代码,以保持假设。在这种情况下,一个重要的假设是我总是通过引用返回值
【解决方案2】:

在这里返回一个指针似乎是合理的,但如果你担心所有权混淆,你可以返回一个围绕引用的包装器。

struct Class {
    struct Ref {
        Ref(Class& c_) : c(c_) { }
        Class Clone() { return c; }
        // overload -> to provide access to c
      private:
        Class& c;
    };
};

原始类可以照常复制,但您必须明确地进行引用。我对这个想法并不热衷(我认为没有意识到复制语义如何工作的用户比不小心持有其中一个太长时间的用户少)但理论上它是可行的。

【讨论】:

    猜你喜欢
    • 2010-12-20
    • 2018-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-04
    • 1970-01-01
    • 2017-05-21
    • 1970-01-01
    相关资源
    最近更新 更多