4

作为任务的一部分,我们被要求创建一个 Vector3D 类,该类使用在堆上分配的内存。我有一个带有以下构造函数的 Vector3DHeap 类。

Vector3DHeap::Vector3DHeap(float& x, float& y, float& z)
{
    this->x = &x;
    this->y = &y;
    this->z = &z;
}

如果我想获得一个单位向量,我希望能够执行以下操作。这会给出错误消息“没有构造函数的实例与参数列表匹配,参数类型是 (float, float, float)。

Vector3DHeap* Vector3DHeap::getUnitVector()
{
    float m = *getMagnitude();

    return new Vector3DHeap((*x / m), (*y / m), (*z / m));
}

如果我定义三个浮点变量 a、b 和 c 并将它们传递给构造函数,编译器会很高兴。上面的代码有什么问题?

Vector3DHeap* Vector3DHeap::getUnitVector()
{
    float m = *getMagnitude();

    float a, b, c;

    a = *x / m;
    b = *y / m;
    c = *z / m;

    return new Vector3DHeap(a, b, c);
}

非常感谢,乔治

4

3 回答 3

10

您对第一个版本的问题是您的编译器正试图防止错误。

您对第二个版本的问题是您超越了编译器并成功地设法创建了一个错误。

给定您的构造函数,您希望存储指向float通过引用传递的值的指针。由于您的第二个版本现在使用对局部变量的引用来调用构造函数float a, b, c;,因此您创建了一个Vector3DHeap引用它们的实例。但是一旦getUnitVector返回,这些变量就不再存在,并且存储在其中的引用Vector3DHeap变成了悬空引用。

解决方案不是在内部存储指针Vector3DHeap或创建参数的副本:

Vector3DHeap::Vector3DHeap(float x, float y, float z)
{
    this->x = new float(x);
    this->y = new float(y);
    this->z = new float(z);
}

不过,请确保正确删除存储的浮点数。

于 2013-10-20T15:34:54.720 回答
1

编译器阻止您将引用绑定到临时对象是一件好事,因为否则您最终会得到一个指向已销毁对象的对象:表达式*x / m和类似的每个都会产生一个临时float对象,该对象将在表达式末尾消失。尝试将临时绑定到非const引用将失败。

但是,我怀疑您是否真的想要这样做:除非您真的知道需要使用指针,否则您不应该使用指针!您的构造函数应该看起来像这样:

Vector3DHeap::Vector3DHeap(float x, float y, float z)
    : x(x), y(y), z(z) {
}

其中成员当然也是 type floatgetMagnitude()也应该返回 a float。...应该getUnitVector()返回 aVector3DHeap而不是指向它的指针!

于 2013-10-20T15:36:30.270 回答
1
  • (*x / m)是一个临时对象。
  • Vector3DHeap(float& x, float& y, float& z)需要一个非常量引用作为第一个参数。

您不能将临时对象传递给需要非常量引用的函数。有关C++ 不允许这样做的详细信息,请参阅https://stackoverflow.com/questions/13826897#13827042 。

于 2013-10-20T15:39:25.993 回答