提问人:Freddy Cansick 提问时间:4/6/2022 更新时间:4/6/2022 访问量:1179
如何使用 C++ 中的 out 参数分配给常量变量?
How do I assign to a const variable using an out parameter in C++?
问:
在类头文件中,我声明了一个 .Texture.h
static const int
static const int MAX_TEXTURE_SLOTS;
在 中,我将变量定义为 。Texture.cpp
0
const int Texture::MAX_TEXTURE_SLOTS = 0;
现在在类的构造函数中,我尝试使用 out 参数分配给变量,但这显然不会编译为 a 而不是 .Window.cpp
&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);
非常感谢。
答:
前提是不依赖于之前调用的其他函数,则可以使用立即调用的 lambda:glGetIntegerv
gl*
// Texture.cpp
const int Texture::MAX_TEXTURE_SLOTS = []
{
int maxTextureSlots{0}:
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureSlots);
return maxTextureSlots;
}();
评论
glGetInteger
const int x = rand();
GLint a, b; …glMakeCurrent(glrc_a, …); glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &a); …glMakeCurrent(glrc_b, …); glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &b);
glGetIntegerv
编辑 2:因此,既然您正在尝试抽象 OpenGL 上下文,那么您必须放弃“传统”构造函数/析构函数的习惯用语。仅供您参考(与此问题无关):OpenGL 上下文与 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);
}
EDIT: I just saw that you intend to use this to hold on to a OpenGL limit. In that case you can't do this on a global scope anyway, since those values depend on the OpenGL context in use. A process may have several OpenGL contexts, each with different limits.
On most computer systems you'll encounter these days, variables declared const in global scope will be placed in memory that has been marked as read only. You literally can't assign to such a variable.
The usual approach to implement global scope runtime constants is by means of query functions that will return from an internal or otherwise concealed or protected value. Like
// 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;
}
You can then fetch the value by calling that function.
评论
determine_value
0
static int x = determine_value(); return x;
x
determine_value()
const
main
You don't.
You can't assign to a const outside of its definition. Also, using a variable where the has been ed away is UB. This also means you can't directly initialize a const variable with an output parameter. For trivial types, just output to another variable and make a const copy if you so wish.const
const
const_cast
If you were the author of the function you're calling, you would do well not to use out parameters, and then you could assign to variables directly, perhaps using structured bindings if you want to name multiple of the outputs at a time. But here, you're not.const
评论
const
const