作为赋值的一部分,我们被要求创建一个使用Heap上分配的内存的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);
}
非常感谢, 乔治
答案 0 :(得分:3)
您对第一个版本的问题是您的编译器正试图阻止错误。
第二个版本的问题在于你超越了编译器并成功设法创建了一个错误。
给定构造函数,您希望存储指向通过引用传递的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);
}
尽管如此,请确保正确删除存储的花车。
答案 1 :(得分:1)
编译器阻止你绑定对临时的引用是好的,否则你最终会得到一个指向已经被破坏的对象的对象:表达式*x / m
和类似的每个都会产生一个临时的{{1对象将在表达式的末尾消失。尝试将临时绑定到非float
引用将失败。
但是,我怀疑你真的想要做任何事情:你不应该使用指针,除非你真的知道你需要使用指针!你的构造函数应该看起来像这样:
const
其中成员当然也是Vector3DHeap::Vector3DHeap(float x, float y, float z)
: x(x), y(y), z(z) {
}
类型。 float
也应该返回getMagnitude()
。 ...... float
应该返回getUnitVector()
而不是指向它的指针!
答案 2 :(得分:1)
(*x / m)
是一个临时对象。Vector3DHeap(float& x, float& y, float& z)
需要非const引用作为第一个参数。您不能将临时对象传递给需要非const引用的函数。有关C ++不希望允许此操作的详细信息,请参阅https://stackoverflow.com/questions/13826897#13827042。