[英]Does return value optimization work, when assigning to a different type?
请考虑以下两类:
class Base
{
Base(const Base& other) {...} // relatively expensive operations here...
Base(int i) {...} // ...here,
virtual ~Base() {...} // ...and here
...
};
class Derived : public Base
{
...
Derived(const Base& other) :Base(other) {...} // some typechecking in here
virtual ~Derived() {}
...
};
这意味着可以通过Derived的第二个构造函数来“转换” Base 。 现在考虑以下代码:
Base getBase()
{
int id = ...
return Base(id);
}
...
int main()
{
Base b = getBase(); // CASE 1
Derived d1(b); // "upcast"
Derived d2 = getBase(); // CASE 2
...
}
我正在使用VS2008并启用了优化功能(/ Ox / Ob2 / Oi / Ot)。 我在控制台输出上检查了对构造函数和析构函数的调用:
在情况1中,返回值优化有效。 有两个电话:
但是,当main中需要派生对象时,这里没有什么可赢得的。 “ upcast”需要另一个构造器/析构器对。
在情况2中,返回值优化无效。 在此创建并销毁了两个对象:
现在在我看来,我有三个相互矛盾的要求:
显然,这里没有免费的午餐。 但是我可能已经错过了一些东西。 所以我的问题是:有没有办法组合这些要求? 还是有人有过类似的经历?
旁注:我知道一个事实,即在运行时,“ upcast”派生的(const Base等)可能会失败(已解决)。 由于代码在语法级别上是可以的,所以我想这不是编译器避免使用RVO的原因。
这不好。
Derived(const Base& other) :Base(other) {...}
other
的静态类型可以属于派生类型。 在这种情况下,它将被切成薄片。 无论如何,将在该基类的顶部进行复制。
RVO是关于绕过复制构造函数并就地初始化返回的对象。 如果需要派生类型的对象,则必须首先构造它。 RVO无法为您构建它。
您可能需要考虑其他方法,而不是Derived(const Base& other)
。 这个怎么样:
class Base
{
...
// extract expensive parts of another instance
virtual void initialise(Base& b);
...
};
class Derived : public Base
{
...
Derived(); // cheap constructor
void initialise(Base& b) { /* implementation goes here */ }
...
};
initialise(Base& b)
方法将从参数中提取昂贵的部分。 它可能具有破坏性。 Base将提供公共(或受保护的)接口来进行实际提取。
如何向Derived
添加构造函数?
Derived(Base (*f)(void)) : Base(f()) { ... }
然后Derived d3 = getBase;
可能会为您带来所需的优化。 由于我不得不在Derived
指定f
的空参数列表,因此可能不是很实际。 但是,使其成为模板构造函数,就可以使用用户编写的函子,它是boost:bind
或C ++ 0x lambda的结果(如果有)。
如果做不到这一点,提取id = ...
的一部分getBase
成一个函数getId
,并给予Derived
构造服用int
该传递id
到它的Base
子对象。 但是,毫无疑问,实际代码比这要复杂得多,这可能会导致拖出很多有关该地点的参数。 也许是轻量级的BaseParameters
类,您可以使用它代替Base
直到实际需要完成缓慢工作的位置,然后将其转换为Base
, Derived
或其他相关类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.