如何在 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
变量,如果您愿意,可以使用结构化绑定一次命名多个输出。但在这里,你不在。
在 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
变量,如果您愿意,可以使用结构化绑定一次命名多个输出。但在这里,你不在。