0

[edit] Outside of this get method (see below), i'd like to have a pointer double * result; and then call the get method, i.e.

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

with that said, I want to a get method that simply sets the result (*&data) by reference, and does not dynamically allocate memory.

The results I am looking for already exist in memory, but they are within C-structs and are not in one continuous block of memory. Fyi, &len is just the length of the array. I want one big array that holds all of the results.

Since the actual results that I am looking for are stored within the native C-struct pointer story_ptr->int_hv[i].ab.center.x;. How would I avoid dynamically allocating memory like I am doing above? I’d like to point the data* to the results, but I just don’t know how to do it. It’s probably something simple I am overlooking… The code is below.

Is this even possible? From what I've read, it is not, but as my username implies, I'm not a software developer. Thanks to all who have replied so far by the way!

Here is a snippet of code:

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;
            }
    }
}
6
  • 1
    Is it actually dynamic allocation (i.e. variable sized data, possibly stored on the heap) you want to avoid? Or is it manual memory management (i.e. use of new/delete, and high risks of memory leaks and dangling pointers) which you are trying to avoid? The first does not necessarily need to be accompanied by the second. Commented Dec 12, 2013 at 18:18
  • Hi Benjamin, it's kind of both that I am trying to avoid. I know the data that I want is in memory somewhere (within the C-structures), so ideally, I'd like a pointer that points to that data and just use that. I guess my main concern is running out of memory (this project is quite large), so I'd like to avoid creating a copy of what's already in memory (avoid new/delete). Commented Dec 12, 2013 at 18:24
  • 1
    I'm not quite certain I get what you want, but it sounds like you need an iterator class. Something that you can return that the client can treat like a pointer, but within the iterator it contains the data and code to lookup and return the values. Commented Dec 12, 2013 at 18:32
  • I've tried to clarify my question by editing the post above. I'm not sure what I want is even possible. It looks like I will have to allocate memory since I absolutely need to return an array of doubles. Commented Dec 12, 2013 at 18:46
  • If you can't change the type you are returning I doubt there's any way to avoid reorganizing your stored values into another array. Commented Dec 12, 2013 at 18:51

3 Answers 3

4

Consider returning a custom accessor class instead of the "double *&data". Depending on your needs that class would look something like this:

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

Sorry for any syntax problems, but you get the idea. Return a reference to this and record this in your map. If done correctly the map with then manage all of the dynamic allocation required.

Sign up to request clarification or add additional context in comments.

1 Comment

Man this is a sweet solution, but the only drawback is I am required to return a double *&. I am definitely going to keep this trick in mind in the future. Thanks!
2

So you want the allocated array to go "down" in the call stack. You can only achieve this allocating it in the heap, using dynamic allocation. Or creating a static variable, since static variables' lifecycle are not controlled by the call stack.

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

If you want to "avoid any allocation", the solution by @Speed8ump is your first choice! But then you will not have your double * result; anymore. You will be turning your "offline" solution (calculates the whole array first, then use the array elsewhere) to an "online" solution (calculates values as they are needed). This is a good refactoring to avoid memory allocation.

1 Comment

Thanks for the reply! Ideally, I'd like to avoid any allocation since it has already been done on the C side of things in their structures. But, I am not sure that what I want is even possible (see edited post). Thanks again :)
0

This answer to this question relies on the lifetime of the doubles you want pointers to. Consider:

// "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 exists and has a value inside pointless_function, but ceases to exist as soon as the function exits. Even if you could get a pointer to it, that pointer would be useless outside of pointless_function. It would be a dangling pointer, and dereferencing it would trigger undefined behavior.

On the other hand, you are correct that if you have data in memory (and you can guarantee it will live long enough for whatever you want to do with it), it can be a great idea to get pointers to that data instead of paying the cost to copy it. However, the main way for data to outlive the function that creates it is to call new, new[], or malloc. You really can't get out of that.

Looking at the code you posted, I don't see how you can avoid new[]-ing up the doubles when you create story. But you can then get pointers to those doubles later without needing to call new or new[] again.


I should mention that pointers to data can be used to modify the original data. Often that can lead to hard-to-track-down bugs. So there are times that it's better to pay the price of copying the data (which you're then free to muck with however you want), or to get a pointer-to-const (in this case const double* or double const*, they are equivalent; a pointer-to-const will give you a compiler error if you try to change the data being pointed to). In fact, that's so often the case that the advice should be inverted: "there are a few times when you don't want to copy or get a pointer-to-const; in those cases you must be very careful."

3 Comments

Data can also outlive the function if the variables are declared static in the function scope.
const double* and double const* are not equivalent!
@ericbn: There are things I always get wrong, so I had to double check const syntax before I posted. Both const double* and double const* are pointers-to-const. double* const is a const pointer that points at mutable data ( stroustrup.com/bs_faq2.html#constplacement , especially last three lines).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.