我对如何使用返回参数从类中获取多个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);
}
这也是我想要的方式。这种方法的缺点是我需要在调用函数中分配正确的内存量,而且我使用的内存比我想象的要多。
答案 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
(即更改只在函数体内有效)
您可以修改 指向的地址的值。虽然b
和a
是不同的变量,但当您调用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 }; }