【问题标题】:passing struct pointers to functions c++将结构指针传递给函数c ++
【发布时间】:2013-09-07 07:15:50
【问题描述】:

应该是一个简单的问题,我有一个结构

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;我可以将它设为一个数组,因为我无法指定 bar 是一个数组,因为它在加载时是一个“未知大小”。 (当实现时,程序将从文件中读取值)这适用于非指针变量,但它的指针我似乎无法理解。

我该如何做,以便在传递结构时可以修改变量指针?

任何帮助将不胜感激!

【问题讨论】:

  • 问题是什么,您要解决什么问题?你的loadFoo 功能很糟糕。

标签: c++ arrays pointers struct


【解决方案1】:

您可以执行您指定的操作,但您给出的确切实现将遇到未定义的行为。

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

【讨论】:

  • 这是我的下一个考虑,从结构更改为类并添加一个方法。如果有空闲时间,这实际上可能是我的选择。
  • @JayPC 在 C++ 中 classstruct 之间确实没有区别。它们本质上是可以互换的。唯一的区别是成员和基类的默认访问。
  • 添加了缺失的“public”:)
【解决方案2】:

您尚未指定问题,但让我猜一下 - 它崩溃和/或没有产生您期望的结果。原因是在data-&gt;bar = nums; 行中分配一个指向局部变量的指针。在这里,您将data-&gt;bar 链接到nums 数组,该数组分配在堆栈上,并在您退出loadFoo 时被释放。结果是您的 Foo 对象内的一个悬空指针。

您可以通过不同的方式解决此问题。最直接的方法是使用带有 size 参数的构造函数 - 这将解决您的 unkonwn size 问题。您需要为data-&gt;bar 显式分配内存并将数据复制到分配的空间中(当然,它需要在不再使用时释放它)。使用loadFoo func 可以达到相同的效果,但使用内部语言功能(构造函数/析构函数)更简洁。

【讨论】:

  • facepalm 忘记了,方法完成后,局部变量会从内存中释放。我了解拥有 Foo(size) 构造函数,但不幸的是,这是一个更大项目的一部分,我在不同位置更改了同一结构的几个部分,所以当我需要 loadFoo() 时,它已经被实例化了。但这解决了我的心理障碍。
【解决方案3】:

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

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

或使用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;}
};

另外,请务必关注rule of three

【讨论】:

  • ... 这可能需要一个析构函数。
  • 正如我在另一条评论中提到的,它是一个更大项目的一小部分,当我实际调用 loadFoo() 时,我已经调用了构造函数并默认了所有变量,因为我修改了一个不同的变量在结构中更早。我会看看我是否可以更快地从文件中加载对象,以便我可以将它与构造函数一起传递。
猜你喜欢
  • 2017-10-02
  • 2020-05-15
  • 2012-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-02
  • 2019-05-03
相关资源
最近更新 更多