c++ - Value Printed 根据其后的指令而变化

标签 c++ cout

我似乎编写了一个时间倒流的类。请允许我解释一下:

我有一个函数 OrthogonalCamera::project(),它将矩阵设置为特定值。然后,我打印出该矩阵的值。

cam.project();

std::cout << "My Projection Matrix: " << std::endl << ProjectionMatrix::getMatrix() << std::endl;

cam.project() 将矩阵插入 ProjectionMatrix 的堆栈(我使用的是 std::stack 容器),ProjectionMatrix::getMatrix() 仅返回栈顶元素。如果我只运行这段代码,我会得到以下输出:

 2      0      0      0      
 0      7.7957 0      0      
 0      0      -0.001 0      
-1     -1      -0.998 1   

但是如果我在std::cout 调用

之后将这些代码运行到
float *foo = new float[16];

Mat4 fooMatrix = foo;

然后我得到这个输出:

 2      0      0      0      
 0     -2      0      0      
 0      0      -0.001 0      
-1      1      -0.998 1    

我的问题如下:我可能会做什么,以便在我打印一个值之后执行的代码会更改正在打印的值?

我正在使用的一些功能:

static void load(Mat4 &set)
{
    if(ProjectionMatrix::matrices.size() > 0)
        ProjectionMatrix::matrices.pop();

    ProjectionMatrix::matrices.push(set);
}
static Mat4 &getMatrix()
{
    return ProjectionMatrix::matrices.top();
}

void OrthogonalCamera::project()
{
    Mat4 orthProjection = { { 2.0f / (this->r - this->l), 0, 0, -1 * ((this->r + this->l) / (this->r - this->l)) },
    { 0, 2.0f / (this->t - this->b), 0, -1 * ((this->t + this->b) / (this->t - this->b)) },
    { 0, 0, -2.0f / (this->farClip - this->nearClip), -1 * ((this->farClip + this->nearClip) / (this->farClip - this->nearClip)) },
    { 0, 0, 0, 1 } }; //this is apparently the projection matrix for an orthographic projection. 

    orthProjection = orthProjection.transpose();

    ProjectionMatrix::load(orthProjection);
}

编辑:谁格式化了我的代码,谢谢。我不太擅长这里的格式,现在看起来好多了:)

进一步编辑:我已验证 fooMatrix 的初始化正在之后我调用 std::cout。

最新编辑:这是初始化 fooMatrix 的函数:

typedef Matrix<float, 4, 4> Mat4;

template<typename T, unsigned int rows, unsigned int cols>
Matrix<T, rows, cols>::Matrix(T *set)
{
    this->matrixData = new T*[rows];

    for (unsigned int i = 0; i < rows; i++)
    {
        this->matrixData[i] = new T[cols];
    }

    unsigned int counter = 0; //because I was too lazy to use set[(i * cols) + j]

    for (unsigned int i = 0; i < rows; i++)
    {
        for (unsigned int j = 0; j < cols; j++)
        {
            this->matrixData[i][j] = set[counter];
            counter++;
        }
    }
}

g64 编辑:这不仅仅是一个输出问题。我实际上必须在其他地方使用矩阵的值,并且它的值与描述的行为一致(无论我是否打印它)。

TREE 第 3 次编辑:通过调试器运行它给了我一个再次不同的值:

-7.559 0      0      0      
0      -2     0      0      
0      0      -0.001 0      
1      1      -0.998 1    

a(g64, g64)th 编辑:在 linux 上编译时不存在该问题。仅在带有 MinGW 的 Windows 上。可能是编译器错误吗?那会让我很难过。

最终编辑:现在可以使用了。我不知道我做了什么,但它有效。我已经确保我使用的是最新版本,它没有确保因果关系仍然有效的代码,并且它有效。感谢您帮助我解决这个问题,stackoverflow 社区。一如既往,你一直乐于助人并容忍我的迟缓。我将高度警惕可能导致这种不可预测性的任何未定义行为或指针错误。

最佳答案

您不是在按指令编写程序指令。您正在向 C++ 编译器描述它的行为,然后它会尝试用机器代码表达相同的行为。

只要可观察的行为没有改变,编译器就可以重新排序您的代码。

换句话说,编译器几乎肯定会重新排序您的代码。那么,为什么可观察到的行为会发生变化?

因为您的代码表现出未定义的行为

同样,您正在编写 C++ 代码。 C++ 是一个标准,一个说明代码“含义”的规范。你在一个契约(Contract)下工作,“只要我,程序员,编写可以根据 C++ 标准解释的代码,那么你,编译器,将生成一个可执行文件,其行为与我的源代码的行为相匹配”。

如果您的代码做了本标准中未指定的任何事情,那么您就违反了本契约(Contract)。您输入了编译器代码,其行为不能根据 C++ 标准进行解释。然后所有赌注都关闭了。编译器信任你。它相信你会履行契约(Contract)。它分析您的代码并基于您将编写具有明确定义的代码的假设生成可执行文件。你没有,所以编译器是在一个错误的假设下工作的。然后它建立在该假设之上的任何东西也是无效的。

垃圾进,垃圾出。 :)

遗憾的是,没有简单的方法来查明错误。您可以仔细研究您的每一段代码,或者您可以尝试在调试器中单步调试有问题的代码。或者在看到“错误”值的地方打入调试器,研究反汇编以及你是如何到达那里的。

这很痛苦,但这对您来说是未定义的行为。 :) 静态分析工具(Linux 上的 Valgrind,并且根据您的 Visual Studio 版本,/analyze 开关可能可用也可能不可用。Clang 内置了类似的选项)可能会有所帮助

关于c++ - Value Printed 根据其后的指令而变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10824740/

相关文章:

c++ - 更改函数以返回指针

c++ - boost::odeint 在成员类中调用

printf - 我可以让 printf 格式像 C++ 流一样 float 吗

c++ - 如何将对 `std::cout` 的引用存储为类成员

c++ - 如何为模板类重载 << cout?

C++ 从 "cout"更改输出

c++ - 程序仅适用于包含(无副作用)cout 语句?

c++ - 动态触发功能

c++ - 在设备上显示 CAknInformationNote

c++ - Excel VBA : "Run-time error ' 4 9': Bad DLL calling convention" calling C++ dll