You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在无动态内存与冗余拷贝下将Table从工厂传给Scheme构造函数?

无动态内存分配的Runge-Kutta Scheme构造方案问题

背景

龙格-库塔格式(Runge-Kutta schemes)由实现于Scheme类的算法,以及名为Table(布彻表,Butcher tableau)的数据组成。我们希望用户仅通过如下语法构造Scheme实例:

Scheme s = Factory::makeSchemeXY();

其中XY标识该格式所使用的特定Table,且Scheme不允许其他构造方式。

当前实现采用表达式模板设计模式,将Table作为表达式模板。由于Table数据量可能极大,示例中使用shared_ptr避免不必要的拷贝与销毁,代码如下:

#include<iostream>
#include<memory>

class Table;
class Factory;
class Scheme;

class Table{
    friend class Factory;
    friend class Scheme;
    double A=0;
    Table(){}
public:
   ~Table(){std::cout<<"~Table\n";}     // only one table is used, hence avoid instantiation of copy
};

class Scheme{
    std::shared_ptr<Table> pt;
    friend class Factory;
    Scheme()=delete;
    void operator=(Scheme const&)=delete;
public:
    Scheme(std::shared_ptr<Table> pt):pt(pt){}
};

struct Factory{
    Factory()=delete;
    static std::shared_ptr<Table> makeSchemeXY(){
        std::shared_ptr<Table> p( new Table ); // heap allocation won't work on some platforms
        p->A = 42; // the table should be constructed here, not in the scheme. That would become too messy.
        return p; // can't we use std::move, or elision, or something here?
    }
};

struct App{
    Scheme x = Factory::makeScheme();   // <--- highly preferred consumer syntax
};

int main(){
    App a;
}

核心问题

我们希望在工厂函数中构造Table并将其作为Scheme的成员存储,但上述实现依赖动态内存分配,无法适配部分嵌入式平台。如何实现无需动态内存分配、也无冗余拷贝的方案?

已尝试方案及问题

  • 让makeScheme返回Table对象,Scheme持有Table类型成员,期望触发拷贝消除,但实际触发两次~Table调用,说明存在冗余拷贝;
  • 在makeScheme的返回语句和Scheme的构造函数初始化列表中使用std::move(t),但Table仍会在两处构造,产生两个实例。

以下是包含拷贝消除与移动语义尝试的代码示例(当前未注释部分可编译,但会触发两次Table实例化):

#include<iostream>

class Table;
class Factory;
class Scheme;

class Table{
    friend class Factory;
    friend class Scheme;
    double A=0;
    Table(){}
public:
   ~Table(){std::cout<<"~Table\n";}
};

class Scheme{
    friend class Factory;
    Scheme()=delete;
    void operator=(Scheme const&)=delete;
    //
    Table t;
public:
    Scheme(Table t):t(t){} // hope for elision
    //Scheme(Table&& t):t(std::move(t)){} // using move
};

struct Factory{
    Factory()=delete;
    static Table makeScheme(){ Table t; t.A=2; return t; } // hope for elision
    //static Table makeScheme(){ Table t; t.A=2; return std::move(t); }
    //static Table&& makeScheme(){ Table t; t.A=2; return std::move(t); } // pardon my futile attempt
};

struct App{
    Scheme x = Factory::makeScheme();
};

int main(){
    App a;
}

备注

尽管Table逻辑上应设为const,但所使用的BLAS接口不支持const类型,因此Scheme中的Table需为非const(实际不会对其进行修改)。


内容的提问来源于stack exchange,提问作者GRamon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 17:44:50