Snowdrama
Snowdrama

Reputation: 415

passing struct pointers to functions c++

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!

Upvotes: 3

Views: 11497

Answers (3)

kfsone
kfsone

Reputation: 24249

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

Upvotes: 2

P0W
P0W

Reputation: 47784

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

Upvotes: 1

SomeWittyUsername
SomeWittyUsername

Reputation: 18338

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.

Upvotes: 2

Related Questions