3

Should be a simple question, I have a struct

struct Foo{
    float *bar;
    Foo(){
        bar = 0;
    }
};

and a load function:

bool loadFoo(Foo *data){
    float nums[4] = {0,1,2,3};
    data->bar = nums;
    return true;
};

And I run it like this:

void main(){
    char data;
    Foo myFoo;
    loadFoo(&myFoo);
    std::cerr << sizeof(myFoo.bar) << "\n";
    std::cerr << myFoo.bar[0] << "\n";
    std::cerr << myFoo.bar[1] << "\n";
    std::cerr << myFoo.bar[2] << "\n";
    std::cerr << myFoo.bar[3];
    std::cin >> data;
};

and the output is 4 bytes for the sizeof(myFoo->bar) I thought by passing the struct to the method I could modify data->bar and since bar is, float *bar; I could make it an array since I cant specify that bar is an array because its an 'unknown size' when loaded. (when implemented the program will read in values from a file) This works fine with non pointer variables but its the pointer that I can't seem to understand.

How do I make it so that when I pass the struct I can modify the variable pointer?

any help would be greatly appreciated!

1
  • 1
    What is the question, and what problem are you trying to solve? Your loadFoo function is quite broken. Commented Sep 7, 2013 at 7:17

3 Answers 3

2

You can do something like you've specified, but the exact implementation you've given will encounter undefined behavior.

bool loadFoo(Foo *data){
    // Create an array of 4 floats ON THE STACK.
    float nums[4] = {0,1,2,3};
    // point data->bar at the above slice of stack.
    data->bar = nums;
    return true;
    // abandon the piece of stack we're pointing at.
}

You might want to look into std::vector as a growable way of storing runtime sizes arrays, or you will need to allocate backing store for the destination floats, e.g.

data->bar = new float[4];

and free it when you are done with it

delete data->bar;

That said; it would seem more elegant to do these operations as members of Foo.

#include <vector>
// #include <algorithm>   // (for the std::copy option)

class Foo
{
    std::vector<float>  m_floats;

public:
    Foo() : m_floats() {}
    void loadFloats()
    {
        m_floats = { 0, 1, 2, 3 };
    }
    // or load them from someplace else
    void loadFloats(float* srcFloats, size_t numFloats)
    {
        m_floats.clear();
        m_floats.reserve(numFloats);

        // copy by hand:
        for (size_t i = 0; i < numFloats; ++i) {
            m_floats.push_back(srcFloats[i]);
        }

        // or just:
        // std::copy(srcFloats, srcFloats + numFloats, m_floats);
    }
};
Sign up to request clarification or add additional context in comments.

3 Comments

That was my next consideration, changing from struct to class and adding a method. This might actually be what I go with given some spare time.
@JayPC there is really no difference between class and struct in C++. They are essentially interchangeable. The only difference is default access of members and base classes.
Added the missing "public" :)
2

You haven't specified the problem but let me guess - it crashes and/or doesn't yield the result you expect. The reason for that is assigning a pointer to a local variable in the line data->bar = nums; Here you link your data->bar to a nums array which is allocated on stack and is freed when you exit loadFoo. The result is a dangling pointer inside your Foo object.

You can solve this in different ways. The most straightforward would be to use a constructor with size parameter - this will solve your unkonwn size issue. You'll need to explicitly allocate memory for the data->bar and copy the data into the allocated space (of course, it will require to free it when not in use anymore). Same effect can be achieved by using your loadFoo func but using internal language features (constructor/destructor) is much cleaner.

1 Comment

facepalm I forgot that after the method was finished, the local variable would be freed from memory. I understand having the Foo(size) constructor but unfortunately this is part of a bigger project that I change a few parts of the same struct in different locations so by the time I get to needing to loadFoo() Its already been instantiated. But this solves my mental roadblock.
1

Instead of loadFoo you can have constructor

struct Foo{
    float *bar;
    Foo( int size){
        bar = new float[size];  //allocate memory
        //... Initialize bar
    }
    ~Foo() { delete bar;}
};

OR using initializer_list

#include <initializer_list>

struct Foo{
    float *bar;
    Foo( std::initializer_list<float> l){
        bar = new float[l.size()];  //allocate memory
        std::initializer_list<float> ::iterator it = l.begin();
        size_t i=0;
        for(;it!=l.end();++it,++i)
          bar[i] = *it;
    }
    ~Foo() { delete bar;}
};

Also, make sure you follow rule of three

2 Comments

... which probably requires a destructor.
As I mentioned in another comment, Its a small piece of a bigger project and by the time i actually call loadFoo() I have already Called the constructor and defaulted all the variables since I modify a different variable in the struct much earlier. I'll look into seeing if I can load the object from file sooner, so that I can pass it with the constructor.

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.