将结构体指针传递给函数C++

3
这是一个简单的问题,我有一个结构体。
struct Foo{
    float *bar;
    Foo(){
        bar = 0;
    }
};

以及一个载入函数:

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

我是这样运行它的:

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

当sizeof(myFoo->bar)返回4个字节时,我以为通过将结构体传递给方法,我可以修改data->bar并且由于bar是float *类型的,所以我可以将其变成数组,因为在加载时无法指定bar是一个数组,因为它的大小未知(当程序实现时,它将从文件中读取值)。这对非指针变量运行良好,但是我似乎无法理解指针。

如何使得我传递结构体时能够修改变量指针?

非常感谢您的任何帮助!


1
你的问题是什么,你试图解决什么问题?你的 loadFoo 函数有很多问题。 - juanchopanza
3个回答

2
你可以像你所描述的那样做一些事情,但是你给出的具体实现将会遇到未定义的行为。
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.
}

您可能需要了解std :: vector作为一种可伸缩的存储运行时大小数组的方法,或者您需要为目标浮点数分配后备存储,例如。
data->bar = new float[4];

当你完成使用后,释放它

delete data->bar;

话虽如此,但似乎更优雅的做法是将这些操作作为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);
    }
};

那是我的下一个考虑,从结构体改为类并添加一个方法。如果有一些空闲时间,这可能是我要采用的方案。 - Snowdrama
1
@JayPC 在C++中,classstruct实际上是可以互换的,它们之间没有什么区别。唯一的区别在于成员和基类的默认访问权限。 - juanchopanza
添加了缺失的 "public" :) - kfsone

2
您没有具体说明问题,但我猜测 - 它会崩溃和/或不能产生您期望的结果。原因是在data->bar = nums;行中将指针分配给本地变量。这里将data->bar链接到在堆栈上分配并在退出loadFoo时释放的nums数组。结果是您的Foo对象内部出现悬空指针。

您可以用不同的方式解决这个问题。最直接的方法是使用带有大小参数的构造函数 - 这将解决您的未知大小问题。您需要显式分配data->bar的内存,并将数据复制到分配的空间中(当然,在不再使用时需要释放它)。通过使用内部语言特性(构造函数/析构函数),可以实现相同的效果,但更加简洁。


面掌 我忘记了方法结束后,局部变量将被释放。我知道有Foo(size)构造函数,但不幸的是,这是一个更大项目的一部分,在不同地点更改相同结构体的几个部分,因此当我需要loadFoo()时,它已经被实例化了。但这解决了我的心理障碍。 - Snowdrama

1

你可以使用构造函数代替loadFoo

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

或者使用{{link1: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;}
};

另外,请确保您遵循三个原则


1
可能需要一个析构函数。 - kfsone
正如我在另一条评论中提到的那样,这只是一个更大项目的一小部分。当我实际调用loadFoo()时,我已经调用了构造函数并默认了所有变量,因为我在结构体中修改了一个不同的变量,而且早在此之前。我会研究一下是否可以更早地从文件加载对象,以便我可以在构造函数中传递它。 - Snowdrama

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接