如何在包装现有类时返回变量效率

问题描述 投票:0回答:1

我正在包装一个现有的库而不会引入太多的开销,使得包装器库可以像现有的一样快地运行。我这样做是为了使接口(语法)与我的旧代码兼容。

比如说,现有的类叫做BASE,它是模板类。我把它包装成如下。

        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;
            }; 

对于没有返回类型的任何成员函数,使用this或* this生成非常有效的代码。但是,当返回类型

  Wrapper<T>

是必需的,调用包装库总是慢5-10倍。由于它只是一个包装类,我需要的所有操作都是提取成员变量“base”(例如“a.base”),使用现有类中的函数对a.base执行某些操作,然后将结果传输到“输出” .base“并返回”输出“。

我必须确保包装类匹配旧代码的旧语法,返回指针不是一个选项。我能想到的解决方法是使用静态变量返回引用。例如,声明这种方式并通过引用返回

      Wrapper<T>& dosomething ( const Wrapper<T>& a)
      {
      static Wrapper<T> output;
      output.base = CallExistingClass(a.base);
      return output;
      }

我想知道是否有更快的方法来做到这一点而不会产生开销/临时?查看转发任何有用的评论。

c++ performance wrapper
1个回答
2
投票

一个简单的优化是使用初始化而不是赋值,例如,

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,这不仅可以避免不必要的值初始化,还可以避免任何复制操作。


另外,要在对象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()的形式称呼它。

© www.soinside.com 2019 - 2024. All rights reserved.