c++ - 为什么 glm::mat3 和 glm::value_ptr 创造了一个穿越时间和宇宙的黑洞,并且正在破坏我脑海中任何可能的逻辑?
问题描述
我正在使用非常著名的 OpenGL 框架创建一个漂亮的图形引擎,但后来我遇到了一个意想不到的问题(就像每个问题一样)。
我必须创建一个函数来修改 glm::mat3 中的特定值。为此,我创建了一个简单的函数,该函数返回一个对 glm::mat3 中特定浮点数的简单引用,但似乎没有任何效果,因为我不知道是什么原因。
这是我的功能:
float& mat3ValueAt(glm::mat3& m, int l, int c) {
// l is the line index and c is the column index...
return glm::value_ptr(m)[3 * l + c];
}
要查看它是否有效,我必须使用一个能够显示我的矩阵的函数:
std::ostream& operator<<(std::ostream& stream, glm::mat3 m) {
for (int i = 0; i < 9; i++) {
stream << GLS::mat3ValueAt(m, i / 3, i % 3) << ((i + 1) % 3 ? ' ' : '\n');
}
return stream;
}
所有这些都不起作用......但没关系......这一定是我的错......所以我将我看起来不错的不起作用的代码减少到我可以找到异常的最小代码......
这就是我最终完全生气的事情,这让我发疯了:
int main() {
glm::mat3 m;
std::cout << "display uninitialised value..." << std::endl;
std::cout << *(glm::value_ptr(m) + 5) << std::endl; // should display an uninitialised value
*(glm::value_ptr(m) + 5) = 42;
std::cout << "display the initialised value" << std::endl;
std::cout << *(glm::value_ptr(m) + 5) << std::endl; // should display 42
}
这个小代码的结果是......
display uninitialised value...
42
display the initialised value
42
所以我之前的两个函数不起作用的事实是好的,也许我只是不知道 value_ptr 是如何工作的......但我很确定一件事......一个值不能有我们的价值'将在分配给它之前分配它!
我放的值而不是 42 并不重要,它总是在我分配之前分配!
这怎么可能?
解决方案
这:
glm::mat3 m;
创建一个未初始化的对象;此对象的内容具有不确定的值。任何读取具有不确定值的对象的值的尝试都会导致未定义的行为。
因此,编译器可以自由地重新排序您的代码,使其如下所示:
int main() {
glm::mat3 m;
*(glm::value_ptr(m) + 5) = 42;
std::cout << "display uninitialised value..." << std::endl;
std::cout << *(glm::value_ptr(m) + 5) << std::endl; // should display an uninitialised value
std::cout << "display the initialised value" << std::endl;
std::cout << *(glm::value_ptr(m) + 5) << std::endl; // should display 42
}
This is perfectly valid because if you tried to read from the value before initializing it, you're in undefined behavior land, and having that value already be initialized is no more correct than any other undefined behavior.
推荐阅读
- sql - 想要年、月、日不同列的周数
- visual-studio-code - Visual Studio Code 仅在从 Linux 上的项目文件夹启动时编译
- amazon-web-services - AWS CDK - 如何调试悬挂部署?
- arrays - 如何将序列转换为数组或 Swift 中的序列是否结束?
- google-apps-script - 谷歌表格剪切和粘贴脚本
- python - 有没有办法通过使用pickle、json等将“_tkinter.tkapp objects”写入文件?- 蟒蛇tkinter
- reactjs - 我在反应时遇到了无效的钩子调用
- java - 为多态类型层次结构杰克逊编写自定义反序列化器
- vue.js - 避免直接改变 prop,因为只要父组件重新渲染,该值就会被覆盖。(Vue路由器)
- arrays - Pyspark在中间读取csv数组列