将代码从使用堆更改为使用堆栈

时间:2019-04-30 16:44:41

标签: c++

具有以下两个使用堆的代码段。我需要更改才能使用堆栈。

  prof_pair_class* ptr_prof_pair = (new prof_pair_class(
        aa_profile
      , bb_profile
      , aa_type
      , bb_type
      ));

   aa_plan = new nPlan(
         aa_prof_analysis
         , prm_segment_data.aa_field.target_gqi
         , prm_segment_data.aa_field.aa_response
         , prm_segment_data.aa.user_type
         );

2 个答案:

答案 0 :(得分:4)

C ++自动/静态/动态/线程存储持续时间对象中有四种对象。

我将在这里讨论的两个是自动和动态。

动态存储持续时间

这些对象是通过new创建的,它们的寿命在传递给delete(或等效数组)时结束。

Type*  val = new Type(<param>);  // Object created here.
                                 // Will live until delete is called on val
                                 // If you forget or there is a bug that misses the delete.
                                 // the object will be leaked.

在现代C ++中,很少见到新的/删除内容,因为内存管理通常是通过容器或智能指针完成的(这防止了手动内存管理,这是C应用程序的祸根)。

自动存储期限

这些对象是在当前本地范围内(在声明时)创建的,并且它们的寿命在控件退出当前范围时结束。

{
    Type  val(<param>);   // declared here
    // STUFF
}                         // end of scope here.
                          // The object's lifespan ends here and
                          // the object is automatically destroyed.

内部对象

自动对象和动态对象都可以存在于类中。对于动态对象,没有任何变化,但是使用构造函数和析构函数有助于正确管理指针的寿命(如果正确完成(请参见5的规则))。

但是对于自动变量,变量的作用域成为其所在对象的生存期。如果父对象是自动对象,则当父对象离开作用域且其生存期结束时,子成员也是如此。如果父级是动态的,则子级成员范围将在父级传递给delete时结束。

class X
{
    Y  val;   // The scope of the automatic member val is X
};               // If the parent object is alive then val is alive.

{
    X  tmp;
}            // tmp goes out of scope. Then tmp is destroyed as is tmp.val

X* ptr = new X;  // the object pointed at by ptr lives until it is deleted.
                 // So its member val will live until the parent is deleted.

以您为例。

要将对象从动态转换为自动,只需停止使用new

// declare a dynamic variable.
prof_pair_class* ptr_prof_pair = new prof_pair_class(
        aa_profile
      , bb_profile
      , aa_type
      , bb_type
      );

{
    // declare an automatic variable.
    prof_pair_class prof_pair(
            aa_profile
          , bb_profile
          , aa_type
          , bb_type
          );
}

传递给功能:

如果您调用的原始函数看起来像这样:

AAAAA_Facade::process_profile_dta(prof_pair_class,
                                  &fg_prof_analysis,
                                  &gf_prof_analysis
                                 );

然后,您需要将呼叫更改为如下所示。

AAAAA_Facade::process_profile_dta(&prof_pair,        // Add the & here.
                                  &fg_prof_analysis,
                                  &gf_prof_analysis
                                 );

原因是该函数需要指向prof_pair_class的指针。因此,预期的类型为prof_pair_class*。自动变量的类型为prof_pair_class,因此我们需要使用地址运算符&将对象转换为指针。

注意:这样做有危险。如果函数期望动态分配的对象,并且您传递了自动对象的地址,则当函数在指针上调用delete时,事情可能会严重出错。因此,您应该确保该函数不希望您传递自有的ptr。

如果您对process_profile_dta()的界面有任何控制权,我将对其进行更改。不应接受指针,而应接受对对象的引用(假设它不拥有所传递对象的所有权)。

namespace AAAAA_Facade
{
    // Pass values by reference.
    // This allows you to access the original objects.
    // But does not imply any ownership transfer
    void process_profile_dta(prof_pair_class&        prof_pair,
                             fg_prof_analysis_class& fg_prof_analysis,
                             gf_prof_analysis_class& gf_prof_analysis
                            );
}

答案 1 :(得分:1)

我可以想到两种方法。最简单的是

 prof_pair_class ptr_prof_pair(
      aa_profile
    , bb_profile
    , aa_type
    , bb_type
    );

最困难的方法是为我们提供一个自定义分配器,该分配器调用alloca和一个智能指针。