对运算符重载和堆与堆栈的混淆

Confusion on operator overloading and heap vs stack

本文关键字:堆栈 运算符 重载      更新时间:2023-10-16

我正在查看以下教程: http://www.videotutorialsrock.com/opengl_tutorial/animation/home.php

此人有一个向量类:

class Vec3f {
private:
float v[3];
public:
Vec3f();
Vec3f(float x, float y, float z);
float &operator[](int index);
float operator[](int index) const;
Vec3f operator*(float scale) const;
Vec3f operator/(float scale) const;
Vec3f operator+(const Vec3f &other) const;
Vec3f operator-(const Vec3f &other) const;
Vec3f operator-() const;
const Vec3f &operator*=(float scale);
const Vec3f &operator/=(float scale);
const Vec3f &operator+=(const Vec3f &other);
const Vec3f &operator-=(const Vec3f &other);
float magnitude() const;
float magnitudeSquared() const;
Vec3f normalize() const;
float dot(const Vec3f &other) const;
Vec3f cross(const Vec3f &other) const;
};

使用示例定义:

Vec3f Vec3f::operator*(float scale) const {
return Vec3f(v[0] * scale, v[1] * scale, v[2] * scale);
}

我对为什么会这样感到困惑。这不应该立即导致分段错误吗?返回值位于堆栈上,应在所有这些函数终止时删除。为什么有效?我对堆栈与堆的理解不正确吗?

编辑:我的理解基于此: 如何在C++中通过引用返回类对象?

Vec3f Vec3f::operator*(float scale) const {
return Vec3f(v[0] * scale, v[1] * scale, v[2] * scale);
}

这使用按值返回,因此返回的是该行创建的类实例的值,而不是实例本身。

这从根本上与return 1;没有什么不同。返回值 1,而不是包含该的任何特定实例或类成员。与几乎所有其他内容一样,实现的责任是弄清楚如何完成代码要求的内容 - 在这种情况下,确保存在某个实例以保存具有适当生存期的返回值。

你可以看看下面的例子:

Vec3f Vec3f::operator*(float scale) const {
return Vec3f(v[0] * scale, v[1] * scale, v[2] * scale);
}
Vec3f a(1,2,3);
Vec3f b;
b = a * 2;

通常会发生以下情况:

  1. 运算符重载实现将使用表示乘法的新参数构造 Ve3f 的新实例。

  2. 返回过程将使用参数中的构造对象调用b的默认复制构造函数。复制构造函数会将字段从其参数复制到"b"的实例。

您始终可以实现自己的复制构造函数来执行默认副本提供的浅层副本之外的其他操作。

Vec3f(const Ver3f &src)...

因此,结果您将获得一个新对象,其中包含从 return 语句中创建的字段复制的所有字段。这是 c++ 中为对象定义的按值返回。

如果通过指针或引用返回对象,结果会有所不同。这将导致内存损坏。

这是二进制乘法运算符,它将Vec3f实例中的数据副本(乘以float scale)返回到右值,以供表达式的其余部分使用。

如何工作已经在什么是右值、左值、x值、gl值和prvalue中得到了答案?

另请参阅 https://en.cppreference.com/w/cpp/language/operator_arithmetic

因此,每个 CPU 都有自己的调用约定。有关更多详细信息,请查看此和此

基本上,返回值或返回值的地址被复制到寄存器中,例如 ARM 中的 R0 和 x86 中的 EAX,以便函数的调用方可以访问它。