如何避免动态分配内存C ++

时间:2013-12-12 18:06:40

标签: c++ c memory memory-management

[edit]在这个get方法之外(见下文),我想要一个指针double * result;,然后调用get方法,即

    // Pull results out
    int story = 3;
double * data;
int len;
m_Scene->GetSectionStoryGrid_m(story, data, len);

据说,我想要一个get方法,它只是通过引用设置结果(*& data),而不是动态分配内存。

我正在寻找的结果已经存在于内存中,但它们在C结构中并且不在一个连续的内存块中。 Fyi,& len只是阵列的长度。我想要一个包含所有结果的大数组。

由于我要查找的实际结果存储在本机C结构指针story_ptr->int_hv[i].ab.center.x;中。我如何避免像上面那样动态分配内存?我想将数据*指向结果,但我不知道该怎么做。这可能是我想要的简单......代码如下。

这甚至可能吗?从我所读到的,它不是,但正如我的用户名暗示,我不是软件开发人员。感谢所有到目前为止回复的人!

以下是一段代码:

void GetSectionStoryGrid_m( int story_number, double *&data, int &len )
{

    std::stringstream LogMessage;

    if (!ValidateStoryNumber(story_number))
    { 
            data = NULL;
            len = -1;
    }
    else
    {
            // Check to see if we already retrieved this result
            if ( m_dStoryNum_To_GridMap_m.find(story_number) == m_dStoryNum_To_GridMap_m.end() )
            {
                    data   = new double[GetSectionNumInternalHazardVolumes()*3];
                    len = GetSectionNumInternalHazardVolumes()*3;

                    Story * story_ptr = m_StoriesInSection.at(story_number-1);
                    int counter = 0;  // counts the current int hv number we are on

                    for ( int i = 0; i < GetSectionNumInternalHazardVolumes() && story_ptr->int_hv != NULL; i++ )  
                    {  
                            data[0 + counter] = story_ptr->int_hv[i].ab.center.x;
                            data[1 + counter] = story_ptr->int_hv[i].ab.center.y;
                            data[2 + counter] = story_ptr->int_hv[i].ab.center.z;

                            m_dStoryNum_To_GridMap_m.insert( std::pair<int, double*>(story_number,data));

                            counter += 3;
                    }
            }
            else
            {
                    data = m_dStoryNum_To_GridMap_m.find(story_number)->second;
                    len = GetSectionNumInternalHazardVolumes()*3;
            }
    }
}

3 个答案:

答案 0 :(得分:4)

考虑返回自定义访问者类而不是“double *&amp; data”。根据您的需要,该类看起来像这样:

class StoryGrid {
    public:
        StoryGrid(int story_index):m_storyIndex(story_index) {
            m_storyPtr =  m_StoriesInSection.at(story_index-1);
        }
        inline int length() { return GetSectionNumInternalHazardVolumes()*3; }

        double &operator[](int index) {
            int i = index / 3;
            int axis = index % 3;
            switch(axis){
                case 0: return m_storyPtr->int_hv[i].ab.center.x;
                case 1: return m_storyPtr->int_hv[i].ab.center.y;
                case 2: return m_storyPtr->int_hv[i].ab.center.z;
            }
        } 
};

对于任何语法问题感到抱歉,但您明白了。返回对此的引用并将其记录在地图中。如果正确完成了地图,则管理所需的所有动态分配。

答案 1 :(得分:2)

所以你希望分配的数组在调用堆栈中“向下”。您只能使用动态分配在堆中分配它。或创建static变量,因为static变量的生命周期不受调用堆栈的控制。

void GetSectionStoryGrid_m( int story_number, double *&data, int &len )
{
    static g_data[DATA_SIZE];
    data = g_data;
    // continues ...

如果您想“避免任何分配”,@ Speed8ump的解决方案是您的首选!但是你不再拥有double * result;了。您将转向“离线”解决方案(首先计算整个阵列,然后在其他地方使用阵列)到“在线”解决方案(根据需要计算值)。这是一个很好的重构,可以避免内存分配。

答案 2 :(得分:0)

这个问题的答案取决于你想要指针的double的生命周期。考虑:

// "pointless" because it takes no input and throws away all its work
void pointless_function()
{
    double foo = 3.14159;
    int j = 0;
    for (int i = 0; i < 10; ++i) {
        j += i;
    }
}

foo存在并且在pointless_function内有一个值,但一旦函数退出就会停止存在。即使你可以获得指向它的指针,该指针在pointless_function之外也是无用的。它将是一个悬空指针,取消引用它将触发undefined behavior

另一方面,你是正确的如果你有内存中的数据(并且你可以保证它能活得足够长,无论你想做什么),它都可以很棒想要获得指向该数据的指针而不是支付复制它的成本。但是,数据生成创建函数的主要方式是调用newnew[]malloc。你真的无法摆脱它。

查看您发布的代码,我看不出您在创建new[]时如何避免story - 双打。但是,您可以稍后获得指向这些双打的指针,而无需再次致电newnew[]


我应该提一下,指向数据的指针可以用来修改原始数据。通常这会导致难以追踪的错误。所以有时候最好付出复制数据的价格(然后你可以自由地捣乱),或者获得指向const的指针(在这种情况下是const double*或{ {1}},它们是等价的;如果你试图改变指向的数据,指向const的指针会给你一个编译错误。实际上,通常情况下建议应该颠倒过来:“有几次你想要复制或获得指向const的指针;在这种情况下你必须要非常小心。“