【问题标题】:avoiding code duplication for const-overload and RVO避免 const-overload 和 RVO 的代码重复
【发布时间】:2015-09-02 22:13:08
【问题描述】:

为了在处理 const-overload 时避免代码重复,我写了这样的东西:

#include <memory>

class A
{
    std::shared_ptr<int> _data;
public:
    const A lightCopy() const
    {
        A a;
        a._data = _data;
        return a;
    }

    A lightCopy()
    {
        using const_a_t = const A;
        const_a_t &const_me = *this;
        return const_me.lightCopy(); // const object here
    }
};

int main()
{
    A a;
    auto b = a.lightCopy();
}

const_cast 用于非常量版本,否则它将是 const 方法中的非常量函数调用,它可能会修改对象并且会在不被注意的情况下逃脱(因为const_cast)。并且从非 const 到 const 的 const 转换不会造成任何问题。

这里的问题是:因为我不能 const_cast 一个对象 - 是否有可能因为调用 lightCopy() 返回 const 对象而实际返回类型不是 const - RVO 将不可能并且额外的副本会制作吗?

【问题讨论】:

  • 如果非const 的行为仍然相同,为什么还要使用它?我意识到这并不能回答你的问题。然而,在真正重要的上下文中,const 和非const 版本的实现或结果往往在某种形式上有所不同,例如,返回引用或具有不同const 限定的指针。 ...并通过值和const 限定它返回一个对象有点无关紧要:显然类型是可复制/可移动的,即用户无论如何都可以获得非const 限定对象。
  • const AA的副本是否额外?
  • @DietmarKühl const-version 在这里是因为我想在父对象不变时允许拥有一个不变的轻量级副本。如果只有非常量版本可用——当父对象是常量时,就无法获得轻量级副本。
  • @nwp 是的,从 const A 复制到 A 是额外的,因为如果我将代码复制粘贴到非 const 版本,就不会有这样的复制。
  • 看来你明白我的意思! ...因为您可以通过简单地复制从 const 限定对象中获取非const 限定对象:A const a; A non_const = a.light_copy(); 您不能在复制时强制传播 constness。

标签: c++ rvo


【解决方案1】:

根据 12.8 [class.copy] 第 31 段列表中的第三项,如果源和目标具有相同的“cv-unqualified type”,则允许临时对象的复制省略:

当一个未绑定到引用(12.2)的临时类对象将被复制/移动到具有相同cv-unqualified类型的类对象时,可以通过直接构造临时对象来省略复制/移动操作进入省略复制/移动的目标

即允许引用的代码复制省略

在原始示例中检测析构函数表明clangIntel's compilerEDG's frontend 删除了副本,而gcc 没有。也就是说,只有两个析构函数调用暗示所有可能的可删除副本都被删除了。无论b 的声明方式如何,副本都会被忽略。我已经使用autoAA const 声明了b

【讨论】:

    猜你喜欢
    • 2011-01-10
    • 1970-01-01
    • 2012-01-28
    • 1970-01-01
    • 1970-01-01
    • 2014-03-07
    相关资源
    最近更新 更多