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 ¢er;
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
初始化的,但它的输出是 0
。 f
持有对 a
的常量引用。这仅仅意味着您不能通过 f.x
修改 a
。这并不意味着 x
不能通过其他方式修改。常量引用不是对常量的引用!
463035818_is_not_a_number 的回答说的完全正确。
但在你的情况下,我认为你的问题是你正在存储对临时变量的引用。
你有:
const Point ¢er;
并且您正在使用 Point(0,0,0)
.
对其进行初始化
您只需更改声明成员的方式,从 const Point ¢er;
到 Point center;
以及从 const Vector &forward;
到 Vector forward;
这样您就不会存储引用,而是存储这些对象的实际副本。
您可以保留您认为对这些成员必不可少的 const
修饰符。
对于一项作业,我获得了一个由不同 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 ¢er;
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
初始化的,但它的输出是 0
。 f
持有对 a
的常量引用。这仅仅意味着您不能通过 f.x
修改 a
。这并不意味着 x
不能通过其他方式修改。常量引用不是对常量的引用!
463035818_is_not_a_number 的回答说的完全正确。
但在你的情况下,我认为你的问题是你正在存储对临时变量的引用。
你有:
const Point ¢er;
并且您正在使用 Point(0,0,0)
.
您只需更改声明成员的方式,从 const Point ¢er;
到 Point center;
以及从 const Vector &forward;
到 Vector forward;
这样您就不会存储引用,而是存储这些对象的实际副本。
您可以保留您认为对这些成员必不可少的 const
修饰符。