You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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方法切换控制的相机,就不能用引用类型存储相机,改用指针类型(指针支持重新指向其他对象),修改点如下:

  1. 把InputManager中的成员声明从引用改为指针,默认初始化为空:
    // 原代码:Camera& m_Camera;
    Camera* m_Camera = nullptr;
    
  2. 修改SetCamera实现,取传入相机的地址赋值给指针:
    void SetCamera(Camera& camera) { m_Camera = &camera; }
    
  3. 后续InputManager中所有访问m_Camera成员的位置,把.访问改为->访问即可,同时可以加个空指针判断避免野指针调用。

注意:不需要为Camera类手动实现拷贝赋值运算符,Camera中持有GLContext全局单例的引用是合理设计,强行实现拷贝赋值反而会破坏原有逻辑。

内容的提问来源于stack exchange,提问作者E D

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 16:01:07