避免 const-overload 和 RVO 的代码重复
avoiding code duplication for const-overload and RVO
为了在处理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 方法中的非 const 函数调用,它可能会修改对象并且会在不被注意的情况下逃脱(因为 const_cast
).从非 const 到 const 的 const 转换应该不会造成任何问题。
这里的问题是:因为我不能 const_cast 对象 — 是否有可能因为调用了 lightCopy()
returns const 对象和实际 return type is not const — RVO 将不可能,并且将制作一个额外的副本?
根据 12.8 [class.copy] 第 31 段列表中的第三项,如果源和目标具有相同的 "cv-unqualified type",则允许复制省略临时对象:
when a temporary class object that has not been bound to a reference (12.2) would be copied/moved to a class object with the same cv-unqualified type, the copy/move operation can be omitted by constructing the temporary object directly into the target of the omitted copy/move
也就是说,引用的代码复制省略是允许的。
在原始示例中检测析构函数表明 clang, Intel's compiler, and EDG's frontend elide the copies while gcc 没有。也就是说,只有两个析构函数调用暗示所有可能的可删除副本都被删除了。副本被省略,与 b
的声明方式无关。我已经使用 auto
、A
和 A const
声明了 b
。
为了在处理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 方法中的非 const 函数调用,它可能会修改对象并且会在不被注意的情况下逃脱(因为 const_cast
).从非 const 到 const 的 const 转换应该不会造成任何问题。
这里的问题是:因为我不能 const_cast 对象 — 是否有可能因为调用了 lightCopy()
returns const 对象和实际 return type is not const — RVO 将不可能,并且将制作一个额外的副本?
根据 12.8 [class.copy] 第 31 段列表中的第三项,如果源和目标具有相同的 "cv-unqualified type",则允许复制省略临时对象:
when a temporary class object that has not been bound to a reference (12.2) would be copied/moved to a class object with the same cv-unqualified type, the copy/move operation can be omitted by constructing the temporary object directly into the target of the omitted copy/move
也就是说,引用的代码复制省略是允许的。
在原始示例中检测析构函数表明 clang, Intel's compiler, and EDG's frontend elide the copies while gcc 没有。也就是说,只有两个析构函数调用暗示所有可能的可删除副本都被删除了。副本被省略,与 b
的声明方式无关。我已经使用 auto
、A
和 A const
声明了 b
。