如何在 C++ 中使用 out 参数分配给 const 变量?

How do I assign to a const variable using an out parameter in C++?

在 class 头文件中 Texture.h 我声明了一个 static const int.

static const int MAX_TEXTURE_SLOTS;

Texture.cpp中我将变量定义为0.

const int Texture::MAX_TEXTURE_SLOTS = 0;

现在在 Window.cpp class 的构造函数中,我尝试使用 out 参数分配给变量,但是这显然不能编译,因为 &Texture::MAX_TEXTURE_SLOTS 指向 const int* 而不是 int* .

glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &Texture::MAX_TEXTURE_SLOTS);

我曾尝试使用 const_cast,但在运行时出现分段错误。

glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, const_cast<int*>(&Texture::MAX_TEXTURE_SLOTS));

我也试过直接转换为 int * 但又一次出现段错误。

glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, (int*)&Texture::MAX_TEXTURE_SLOTS);

非常感谢。

前提是 glGetIntegerv 不依赖于之前调用的其他 gl* 函数,您可以使用 immediately-invoked lambda:

// Texture.cpp

const int Texture::MAX_TEXTURE_SLOTS = []
{
    int maxTextureSlots{0}:
    glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureSlots);
    return maxTextureSlots;
}();

编辑 2:因此,由于您正在尝试抽象 OpenGL 上下文,因此您必须放弃“传统”constructor/destructor 习语。仅供参考(与此问题无关):OpenGL 上下文与 windows! 无关,只要一组 windows 和 OpenGL 上下文兼容彼此之间,您可以按照自己喜欢的方式混合搭配。但是我跑题了。

处理像您这样的情况的标准习惯用法是使用预初始化工厂函数。像这样:

class MyOpenGLContextWrapper {
public:
    // Yes, shared_ptr; using a unique_ptr here for objects that are kind
    // of a nexus for other things -- like an OpenGL context -- just creates
    // a lot of pain and misery. Trust me, I know what I'm talkink about.
    typedef std::shared_ptr<MyOpenGLContextWrapper> ptr;

    struct constdata {
        NativeGLContextType context;
        // ...
        GLint max_texture_image_units;
        // ...
    };

    static ptr create();

protected:
    MyOpenGLContextWrapper(constdata const &cdata) : c(cdata) {};
    virtual ~MyOpenGLContextWrapper();
    constdata const c;
}

MyOpenGLContextWrapper::ptr MyOpenGLContextWrapper::create()
{
    struct object : public MyOpenGLContextWrapper {
        object(MyOpenGLContextWrapper::constdata const &cdata) : MyOpenGLContextWrapper(cdata) {}
        ~object(){}
    };

    MyOpenGLContextWrapper::constdata cdata = {};

    // of course this should all also do error checking and failure rollbacks
    cdata.context = create_opengl_context();
    bind_opengl_context(cdata.context);
    // ...
    glGetInteger(GL_MAX_TEXTURE_IMAGE_UNITS, &cdata.max_texture_image_units);

    return std::make_shared<object>(cdata);
}

编辑:我刚刚看到您打算使用它来保持 OpenGL 限制。在那种情况下,您无论如何都不能在全局范围内执行此操作,因为这些值取决于所使用的 OpenGL 上下文。一个进程可能有多个 OpenGL 上下文,每个都有不同的限制。


在您现在遇到的大多数计算机系统上,在全局范围内声明为 const 的变量将被放置在已标记为只读 的内存中。您实际上不能分配给这样的变量。

实现全局作用域运行时常量的常用方法是通过查询函数return 来自内部或其他隐藏或受保护的值。喜欢

// header.h
int runtime_constant();
#define RUNTIME_CONSTANT runtime_constant()

// implementation.c / .cpp
int runtime_constant_query(){
    static int x = 0;
    // NOTE: This is not thread safe!
    if( !x ){ x = determine_value(); }
    return x;
}

然后您可以通过调用该函数获取值。

你不知道。

您不能将其赋值给定义之外的 const。此外,使用 const 变量,其中 const 已被 const_cast 删除是 UB。这也意味着您不能直接使用输出参数初始化 const 变量。对于普通类型,只需输出到另一个变量并根据需要制作一个 const 副本。

如果您是所调用函数的作者,最好不要使用 out 参数,然后您可以直接分配给 const 变量,如果您愿意,可以使用结构化绑定一次命名多个输出。但在这里,你不在。