C++:由 const 引用传递的变量更改值

C++: Variable that is passed by const referance changes value

对于一项作业,我获得了一个由不同 classes 组成的框架,这些框架使用通过 const 引用传递的参数。当我初始化同一个 class 的一个实例,然后再初始化第二个实例时,第一个实例中由 const 引用传递的成员的值发生变化。
我不允许更改a_cameras。我可以在 class 定义中做些什么来避免值自行改变吗?

PerspectiveCamera 的初始化:

#include <core/image.h>
#include <core/point.h>
#include <core/vector.h>
#include <core/scalar.h>
#include <core/julia.h>
#include <rt/ray.h>
#include <rt/cameras/perspective.h>
#include <rt/cameras/orthographic.h>
#include <iostream>
#include <rt/renderer.h>

using namespace rt;


void a_cameras() {
    Image img(800, 800);
    Image low(128, 128);

    PerspectiveCamera pcam(Point(0, 0, 0), Vector(1, 0, 0.1f), Vector(0, 0, 1), pi/3, pi/3);
    Renderer r1(&pcam,0);
    r1.test_render2(img);
    r1.test_render2(low);
    img.writePNG("a1-2.png");
    low.writePNG("a1-2-low.png");

    PerspectiveCamera pcam2(Point(0, 0, 0), Vector(0.5f, 0.5f, 0.3f), Vector(0, 0, 1), pi * 0.9f, pi * 0.9f);
    Renderer r12(&pcam2,0);
    r12.test_render2(img);
    img.writePNG("a1-3.png");

    OrthographicCamera ocam(Point(0, 0, 0), Vector(0.1f, 0.1f, 1), Vector(0.2f, 1.0f, 0.2f), 10.f, 10.f);
    Renderer r2(&ocam,0);
    r2.test_render2(img);
    img.writePNG("a1-4.png");
}

PerspectiveCamera的定义 perspective.cpp:

#include <rt/cameras/perspective.h>
#include <cmath>
#include <core/matrix.h>

namespace rt {

PerspectiveCamera::PerspectiveCamera(const Point& center, const Vector& forward, const Vector& up, float verticalOpeningAngle, float horizontalOpeningAngle)
: center(center), forward(forward)
{
    vertFactor = tanf(verticalOpeningAngle / 2.0f);
    horFactor = tanf(horizontalOpeningAngle / 2.0f);
    x_axis = cross(forward, up).normalize();
    up_axis = cross(x_axis, forward).normalize();
    //vertFactor = tanf(verticalOpeningAngle / 2.0f);
    //horFactor = tanf(horizontalOpeningAngle / 2.0f);
}

Ray PerspectiveCamera::getPrimaryRay(float x, float y) const {
    printf("center: (%f, %f, %f); forward: (%f, %f, %f); x_axis: (%f, %f, %f); up_axis: (%f, %f, %f)\n",
           center.x, center.y, center.z,forward.x, forward.y, forward.z, x_axis.x, x_axis.y, x_axis.z, up_axis.x, up_axis.y, up_axis.z);
    Vector direction = x * x_axis * horFactor + y * up_axis * vertFactor + forward;
    return {center, direction};
}

}

perspective.h:

#ifndef CG1RAYTRACER_CAMERAS_PERSPECTIVE_HEADER
#define CG1RAYTRACER_CAMERAS_PERSPECTIVE_HEADER

#include <rt/cameras/camera.h>
#include <core/vector.h>
#include <core/point.h>

namespace rt {

class PerspectiveCamera : public Camera {
public:
    PerspectiveCamera(
        const Point& center,
        const Vector& forward,
        const Vector& up,
        float verticalOpeningAngle,
        float horizontalOpeningAngle
        );

    virtual Ray getPrimaryRay(float x, float y) const;

    const Point &center;
    const Vector &forward;
    Vector x_axis;
    Vector up_axis;
    float vertFactor;
    float horFactor;
};

}


#endif

谢谢, 简

你的代码比较复杂。尽管需要更少的东西来证明这个假设:“const 引用不会改变它的值。”是基于误解。

#include <iostream>
    
struct foo {
    const int& x;
};

int main()
{
    int a = 42;
    foo f{a};
    a = 0;
    std::cout << f.x;
}

尽管 f.x 是在 a 的值为 42 时使用 a 初始化的,但它的输出是 0f 持有对 a 的常量引用。这仅仅意味着您不能通过 f.x 修改 a。这并不意味着 x 不能通过其他方式修改。常量引用不是对常量的引用!

463035818_is_not_a_number 的回答说的完全正确。

但在你的情况下,我认为你的问题是你正在存储对临时变量的引用。

你有: const Point &center; 并且您正在使用 Point(0,0,0).

对其进行初始化

您只需更改声明成员的方式,从 const Point &center;Point center; 以及从 const Vector &forward;Vector forward;

这样您就不会存储引用,而是存储这些对象的实际副本。 您可以保留您认为对这些成员必不可少的 const 修饰符。