C++编译报错:Camera隐式拷贝赋值运算符为已删除函数无法引用
问题现象
C++图形程序开发时遇到编译错误:Error: function Camera::operator=(const Camera&) (declared implicitly) cannot be referenced -- it is a deleted function
即无法引用Camera类隐式声明的拷贝赋值运算符,该函数为已删除函数。
错误触发位置为InputManager.h中的如下代码:
void SetCamera(Camera& camera) { m_Camera = camera; }
涉及的两个核心头文件代码如下:
Camera.h 代码
#include "math_headers.h" #include "GLContext.h" static const float YAW = -90.0f; static const float PITCH = 0.0f; static const float SPEED = 2.5f; static const float SENSITIVITY = 0.1f; static const float ZOOM = 45.0f; class Camera { public: Camera(glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f), float yaw = YAW, float pitch = PITCH) : m_Front(glm::vec3(0.0f, 0.0f, -1.0f)), m_MovementSpeed(SPEED), m_MouseSensitivity(SENSITIVITY), m_Zoom(ZOOM), m_Position(position), m_WorldUp(up), m_Yaw(yaw), m_Pitch(pitch), m_Context(GLContext::getTnstance()) { updateCameraVectors(); } Camera(float posX, float posY, float posZ, float upX, float upY, float upZ, float yaw, float pitch) : m_Front(glm::vec3(0.0f, 0.0f, -1.0f)), m_MovementSpeed(SPEED), m_MouseSensitivity(SENSITIVITY), m_Zoom(ZOOM), m_Position(glm::vec3(posX, posY, posZ)), m_WorldUp(glm::vec3(upX, upY, upZ)), m_Yaw(yaw), m_Pitch(pitch), m_Context(GLContext::getTnstance()) { updateCameraVectors(); } inline void MoveForward() { m_Position += m_Front * Velocity(); } inline void MoveBackward() { m_Position -= m_Front * Velocity(); } inline void MoveLeft() { m_Position += m_Right * Velocity(); } inline void MoveRight() { m_Position -= m_Front * Velocity(); } glm::mat4 GetViewMatrix() { return glm::lookAt(m_Position, m_Position + m_Front, m_Up); } inline const glm::vec3& Position() const { return m_Position; } inline const glm::vec3& Up() const { return m_Up; } inline const glm::vec3& Front() const { return m_Front; } inline const glm::vec3& Right() const { return m_Right; } ~Camera() {} private: void updateCameraVectors(); inline const float Velocity() const { return m_MovementSpeed * m_Context.DeltaTime(); } GLContext& m_Context; glm::vec3 m_Position; glm::vec3 m_Up; glm::vec3 m_Front; glm::vec3 m_Right; glm::vec3 m_WorldUp; float m_Yaw; float m_Pitch; float m_MovementSpeed; float m_MouseSensitivity; float m_Zoom; };
InputManager.h 代码
#pragma once #include <vector> #include "GLContext.h" #include "Keybind.h" #include "Camera.h" class InputManager { private: using cursor_pos_callback = void (*)(GLFWwindow* window, double xpos, double ypos); public: static InputManager& getTnstance(cursor_pos_callback = NULL); void ProcessInput() const; void SetCamera(Camera& camera) { m_Camera = camera; } inline void SetCursor(const float x, const float y) { m_CursorX = x; m_CursorY = y; } inline void GetCursor(float& x, float& y) { x = m_CursorX; y = m_CursorY; } template<typename T> void RegisterKeybind(int keyId); ~InputManager(); InputManager(InputManager const&) = delete; void operator=(InputManager const&) = delete; private: InputManager(cursor_pos_callback); void SetGlobalSettings(); Camera& m_Camera; GLContext& m_Context; float m_CursorX; float m_CursorY; std::vector<Keybind*> m_Keybinds; cursor_pos_callback m_CursorPosCallback; };
错误根因
错误由两层问题共同导致:
- C++语法规则限制:类如果包含非静态引用类型成员,编译器会自动将隐式生成的拷贝赋值运算符标记为删除。原因是引用一旦在构造时绑定到某个对象,后续就无法重新绑定到其他对象,默认的逐成员拷贝赋值逻辑对引用成员无效。
你的Camera类中存在GLContext& m_Context;这个引用成员,因此Camera的隐式operator=本来就是被删除的,无法调用。 - 代码逻辑错误:
InputManager中的m_Camera也是Camera&引用类型,你在SetCamera中写m_Camera = camera;时,并不是让m_Camera重新绑定到传入的camera参数——C++不支持引用重绑定,这行代码的实际语义是调用Camera的拷贝赋值运算符,把参数camera的所有成员值,拷贝赋值给m_Camera当前已经绑定的那个Camera对象。这一步刚好触发了对已删除的Camera拷贝赋值运算符的调用,直接报编译错误。
修复方案
根据你的设计意图二选一即可:
方案1:InputManager生命周期内不需要切换绑定的相机
如果InputManager从创建到销毁始终操作同一个Camera对象,直接删除SetCamera方法,在InputManager的构造函数初始化列表中完成m_Camera的绑定即可,不需要后续赋值。
方案2:需要动态切换InputManager操作的相机对象
如果确实需要通过SetCamera方法切换控制的相机,就不能用引用类型存储相机,改用指针类型(指针支持重新指向其他对象),修改点如下:
- 把InputManager中的成员声明从引用改为指针,默认初始化为空:
// 原代码:Camera& m_Camera; Camera* m_Camera = nullptr; - 修改
SetCamera实现,取传入相机的地址赋值给指针:void SetCamera(Camera& camera) { m_Camera = &camera; } - 后续InputManager中所有访问m_Camera成员的位置,把
.访问改为->访问即可,同时可以加个空指针判断避免野指针调用。
注意:不需要为Camera类手动实现拷贝赋值运算符,Camera中持有GLContext全局单例的引用是合理设计,强行实现拷贝赋值反而会破坏原有逻辑。
内容的提问来源于stack exchange,提问作者E D
相关产品推荐
相关产品推荐

