如何正确返回类成员数组作为返回参数

时间:2014-06-03 14:59:12

标签: c++ arrays pointers

我对如何使用返回参数从类中获取多个float数组感到困惑。这是一个简化的例子。

class Points
{
    private:
        float *x;
        float *y;
        float *z;
    public:
        void getCoordinates (float *retx, float *rety, float *retz);
}

void Points:: getCoordinates (float *retx, float *rety, float *retz)
{
    retx=x;
    rety=y;
    retz=z;
}

当我在函数内部进行赋值时,指针值匹配。但是,一旦我离开函数,值就会改变。指针的范围是否有限?

基于How to properly return an array (class member) in C++?,我不认为应该是这种情况。讨论表明,不仅可以传递指针,而且通过指针对内存的更改将影响类的原始实例。究竟我希望指针能起作用。

我尝试过的一个方法是使用memcpy

void Points::getCoordinates (float *retx, float *rety, float *retz)
 {
memcpy(retx, x, sizeof(float)*numPoints);
memcpy(rety, y, sizeof(float)*numPoints);
memcpy(retz, z, sizeof(float)*numPoints);   
}

这也是我想要的方式。这种方法的缺点是我需要在调用函数中分配正确的内存量,而且我使用的内存比我想象的要多。

2 个答案:

答案 0 :(得分:2)

您需要使用指针引用。

    void Points:: getCoordinates (float *&retx, float *&rety, float *&retz)

答案 1 :(得分:2)

  

但是,一旦我离开该功能,值就会改变。指针的范围是否有限?

这是应该的。

考虑以下代码:

int f(int a) { a = 20; }

int x = 10;
f(x);

当您致电f时,会在堆栈上创建一个位置,其中放置x(10)中的值。然后,这个地方被命名为a,并且为具有值x的a执行该函数。如果修改a(如上面的代码中所示),则不修改x,因为x是一个不同的变量。

现在,考虑当a是指针时会发生什么:

int g(int *a) { a = nullptr; }
int *b = new int{10};
g(b);

这里,在a的堆栈上创建的值是一个内存地址。如果你修改地址本身(如果你做a = nullptr;),与上面的情况类似,b不受影响,只有a(即更改只在函数体内有效)

您可以修改 指向的地址的值。虽然ba是不同的变量,但当您调用g(b)时,两个变量(尽管不同)将包含相同的内存地址。因此,如果您更改a指向的地址处的值,则表示您已生效,将值返回给客户端代码(您实际上并没有返回它,但客户端代码可以访问它,de - 引用b)。

代码:

int g(int *a) { *a = 20; } // assign value to memory pointed to, by a
int *b = new int{10};
g(b); // a and b will point to the same value
assert(*b == 20); // evaluates to true

这是使用输出参数的 C风格。在C中,输出参数是一个包含地址的参数,因此修改该地址的值允许客户端代码访问该地址(如上例所示)。

在具体情况下,您的代码可以这样编写(但可能不应该 - 见下文):

void Points::getCoordinates (float **retx, float **rety, float **retz)
{
    *retx=x;
    *rety=y;
    *retz=z;
}

每个参数都有一个额外的间接级别(即如果你希望你的输出参数将地址保存到一个浮点数,你必须把一个指向该地址的指针作为一个参数 - 即一个双指针,或指向指向浮点数的指针。

为什么你不应该

C ++引入了引用,它允许将地址视为对象本身。 因此,对于C ++,您的代码可能如下所示:

void Points::getCoordinates (float *&retx, float *&rety, float *&retz)
{
    retx=x;
    rety=y;
    retz=z;
}

更好的是,在C ++中,您的代码可能看起来像这样(不确定这对您的代码/代码库是否可行):

struct Point3d { float x, y, z; }
Point3d Points::getCoordinates() const { return Point3d{ x, y, z }; }