【问题标题】:Efficient factory functions without pointers (including smart pointers) or copies?没有指针(包括智能指针)或副本的高效工厂函数?
【发布时间】:2011-08-13 15:34:21
【问题描述】:

假设我有某种工厂函数,它创建的对象主要用于很短的时间跨度(可能只是在调用此工厂函数的函数范围内)。

像这样:

foo factory(some_parameter fancy_parameter)
{
   return foo(fancy_parameter);
}

//this gets called all the time... very often
void every_frame_function()
{
   for(int i=0; i<big_number; ++i)
       do_something_with(factory(some_parameter(i));

} //don't need those foos out here!

有没有一种方法可以实现这样的工厂,而无需用户关心内存管理(通过返回指针),无需处理智能指针开销,也无需返回必须硬拷贝的 foo 对象?

也许我要的是一只在这里下金蛋的鹅,但也许这里需要使用一些移动语义(我只是不知道如何)。

【问题讨论】:

  • 你真的想在每次调用 factory() 时都创建一个新工厂吗?还是每次工作都返回同一家工厂?智能指针还有什么问题?它们是现代 C++ 工作的基础。
  • 工厂函数似乎要解决什么问题?
  • 对于(2D-)碰撞检测,我需要边界框,其中包含 13 个二维向量(4 个角顶点、4 个边缘顶点、4 个法线顶点和一个中心顶点,总共 26 个浮点数)。工厂函数用于创建某些类型的边界框。大多数这些边界框都被永久保存;但是,我也有很多动态创建的对象,我需要为每个对象创建边界框。这不是性能杀手,我也不喜欢过早的优化,但我问是否有一些东西可以在没有黑客攻击的情况下轻松实现。

标签: c++ performance factory


【解决方案1】:

使用std::unique_ptr&lt;T&gt;,与原始指针相比,它的开销为零。

或者只是按值返回,但是你不能做子类型多态。

【讨论】:

    【解决方案2】:

    编译器在许多情况下会优化副本,具体取决于您对它的处理方式。例如:

    type create();
    void test {
       type local = create();       // Copy will be elided
       type const & ref = create(); // Extra copy will be elided
       local = create();
    }
    

    这是假设 create 以可以应用 (N)RVO 的方式实现,否则在从 create 返回之前会有另一个内部副本之前

    现在,有趣的是确定这是否是正确的方法,我们无法做到这一点,因为您没有提供有关问题的足够信息。例如,工厂返回的对象创建成本有多大,它们是否持有资源,或者您是否可以重用该对象......

    【讨论】:

    • 厌倦了衍生工厂的切片。
    【解决方案3】:

    我认为这是深拷贝和浅拷贝的问题。指针类似于浅拷贝。

    两个副本的详细信息:http://en.wikipedia.org/wiki/Object_copy#In_C.2B.2B

    如果不在另一个函数中使用指针,您必须在代码中使用深拷贝。如果对象很大,深拷贝会耗费很多时间,导致程序很慢。在您关于二维向量的示例中,两个副本之间的差异并不明显。但是如果对象大到复杂的对话框,效果就很清晰了。

    【讨论】:

      【解决方案4】:

      嗯,你不能用工厂函数来做,但你可以用类来做:

      class Factory {
      public:
         Base &create_obj(some_param p)
         {
            d.p =p;
            return d;
         }
       private:
         Derived d;
      };
      void every_frame_function() {
         Factory f;
         for(int i=0;i<bignumber;i++)
           {
           do_something_with(f.create_obj(some_parameter(i)));
           }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多