我正在包装一个现有的库,而不会引入太多的开销,这样包装器库就可以像现有的库一样快地运行。我这样做是为了使接口(语法)与我的旧代码兼容。
比方说,现有的类称为基类,它是模板化类。我把它包装如下。
template<class T>
class Wrapper{
public:
Wrapper() : base(){};
/* ... */
Wrapper<T> dosomething ( const Wrapper<T>& a )
{
Wrapper<T> output;
output.base = CallExistingClass(a.base);
return output;
}
private:
BASE<T> base;
}; 对于没有返回类型的任何成员函数,使用这个或*这会产生非常有效的代码。但是,当返回类型为
Wrapper<T>这是必需的,调用包装库总是慢5-10倍。因为它只是一个包装类,所以我所需要的操作就是提取成员变量“base”(如" a.base "),使用现有类中的函数对a.base做一些事情,然后将结果传递到"output.base“并返回"output”。
我必须确保包装器类与旧代码的旧语法相匹配,这里不能选择返回by指针。我可以想到的工作是使用静态variable.For示例按引用返回,以这种方式声明并按引用返回。
Wrapper<T>& dosomething ( const Wrapper<T>& a)
{
static Wrapper<T> output;
output.base = CallExistingClass(a.base);
return output;
}我想知道是否有更快的方法来做到这一点而不引起开销/临时的?查看转发任何有用的评论。
发布于 2017-12-26 08:06:09
一个简单的优化是使用初始化而不是赋值。
template <class... U>
Wrapper(U&&... args) : base(std::forward<U>(args)...) {} // forward constructor
Wrapper<T> dosomething ( const Wrapper<T>& a )
{
Wrapper<T> output{CallExistingClass(a.base)};
return output;
}由于复制省略的存在,这不仅可以避免不必要的值初始化,而且可以避免任何复制操作.
此外,要在对象dosomething上调用a,对于当前的声明,您应该创建一个额外的对象(例如w),并以w.dosomething(a)形式调用它。要改善这一点,有两种方法。
(1)请注意,dosomething的效果不依赖于数据成员,因此您可以将其声明为static。
static Wrapper<T> dosomething ( const Wrapper<T>& a )
{
//...
}然后,您可以在表单Wrapper<T>::dosomething(a)中使用它,而无需创建额外的对象。
(2)此外,您还可以使用数据成员而不是参数。
Wrapper<T> dosomething const ()
{
Wrapper<T> output{CallExistingClass(base)};
return output;
}并以a.dosomeghing()形式调用它。
https://stackoverflow.com/questions/47974847
复制相似问题