如何在包装现有 class 时使变量的 return 有效
How to make return of variable efficient when wrapping existing class
我在不引入太多开销的情况下包装现有的库,这样包装库可以 运行 与现有的库一样快。我这样做是为了使界面(语法)与我的旧代码兼容。
比如说,现有的class被称为BASE,模板化class。我将其包装如下。
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;
};
对于没有 return 类型的任何成员函数,使用 this 或 *this 生成非常高效的代码。但是,当 return 类型的
Wrapper<T>
是必需的,调用包装库总是慢 5-10 倍。由于它只是一个包装器 class,我需要的所有操作是提取成员变量 "base"(例如 "a.base"),使用现有 a.base 中的函数做一些事情 class,然后将结果传送到"output.base"和return"output"。
我必须确保包装器 class 与我的旧代码的旧语法匹配,return 指针不是这里的选项。我能想到的解决方法是 return-by-reference with static variable.For example,声明这种方式和 return-by-reference
Wrapper<T>& dosomething ( const Wrapper<T>& a)
{
static Wrapper<T> output;
output.base = CallExistingClass(a.base);
return output;
}
我想知道是否有更快的方法来做到这一点而不会招致 overhead/temporary?期待任何有用的评论。
一个简单的优化是使用初始化而不是赋值,例如
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;
}
因为copy elision,这不仅可以避免不必要的值初始化,还可以避免任何复制操作。
此外,要在对象 a
上调用 dosomething
,您应该为当前声明创建一个额外的对象(比如 w
),并以 w
的形式调用它=16=]。要改善这一点,有两种方法。
(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()
.
的形式调用它
我在不引入太多开销的情况下包装现有的库,这样包装库可以 运行 与现有的库一样快。我这样做是为了使界面(语法)与我的旧代码兼容。
比如说,现有的class被称为BASE,模板化class。我将其包装如下。
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;
};
对于没有 return 类型的任何成员函数,使用 this 或 *this 生成非常高效的代码。但是,当 return 类型的
Wrapper<T>
是必需的,调用包装库总是慢 5-10 倍。由于它只是一个包装器 class,我需要的所有操作是提取成员变量 "base"(例如 "a.base"),使用现有 a.base 中的函数做一些事情 class,然后将结果传送到"output.base"和return"output"。
我必须确保包装器 class 与我的旧代码的旧语法匹配,return 指针不是这里的选项。我能想到的解决方法是 return-by-reference with static variable.For example,声明这种方式和 return-by-reference
Wrapper<T>& dosomething ( const Wrapper<T>& a)
{
static Wrapper<T> output;
output.base = CallExistingClass(a.base);
return output;
}
我想知道是否有更快的方法来做到这一点而不会招致 overhead/temporary?期待任何有用的评论。
一个简单的优化是使用初始化而不是赋值,例如
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;
}
因为copy elision,这不仅可以避免不必要的值初始化,还可以避免任何复制操作。
此外,要在对象 a
上调用 dosomething
,您应该为当前声明创建一个额外的对象(比如 w
),并以 w
的形式调用它=16=]。要改善这一点,有两种方法。
(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()
.