考虑以下代码:

Matrix4x4 perspective(const ViewFrustum &frustum) {
    float l = frustum.l;
    float r = frustum.r;
    float b = frustum.b;
    float t = frustum.t;
    float n = frustum.n;
    float f = frustum.f;

    return {
        { 2 * n / (r - l), 0,               (r + l) / (r - l),    0                      },
        { 0,               2 * n / (t - b), (t + b) / (t - b),    0                      },
        { 0,               0,               -((f + n) / (f - n)), -(2 * n * f / (f - n)) },
        { 0,               0,               -1,                   0                      }
    };
}

为了提高构造矩阵的可读性,我必须从视锥结构复制值或对其进行引用。但是,我实际上都不需要拷贝或间接拷贝。

是否有可能在编译时解决某种“引用”,就像符号链接(symbolic link)一样。它将具有与以下相同的效果:
Matrix4x4 perspective(const ViewFrustum &frustum) {
    #define l frustum.l;
    #define r frustum.r;
    #define b frustum.b;
    #define t frustum.t;
    #define n frustum.n;
    #define f frustum.f;

    return {
        { 2 * n / (r - l), 0,               (r + l) / (r - l),    0                      },
        { 0,               2 * n / (t - b), (t + b) / (t - b),    0                      },
        { 0,               0,               -((f + n) / (f - n)), -(2 * n * f / (f - n)) },
        { 0,               0,               -1,                   0                      }
    };

    #undef l
    #undef r
    #undef b
    #undef t
    #undef n
    #undef f
}

没有预处理器(或者可以接受吗?)。我想这并不是真正需要的,或者在这种特殊情况下可以通过直接将这6个值作为函数的参数来避免(尽管这样调用该函数会有些烦人-但即使那样,我仍然可以内联代理功能)。

但是我只是想知道这是否总有可能吗?我找不到类似的东西。我认为这对于在本地简化将经常使用的描述性名称非常有用,而不必实际丢失原始名称。

最佳答案

强制性免责声明:不要过早优化。

让我比较一下您朴素的perspective函数,其中包含

float l = frustum.l;
float r = frustum.r;
float b = frustum.b;
float t = frustum.t;
float n = frustum.n;
float f = frustum.f;

define和@Sam Varshavchik解决方案一起使用。

我们假设我们的编译器正在优化,并且至少优化得不错。

所有三个版本的汇编输出:https://godbolt.org/g/G06Bx8

您会注意到引用版本和定义版本完全相同-符合预期。但是天真相差很多。它首先从内存中加载所有值:
    movss   (%rdi), %xmm2           # xmm2 = mem[0],zero,zero,zero
    movss   4(%rdi), %xmm1          # xmm1 = mem[0],zero,zero,zero
    movss   8(%rdi), %xmm0          # xmm0 = mem[0],zero,zero,zero
    movss   %xmm0, 12(%rsp)         # 4-byte Spill
    movss   12(%rdi), %xmm0         # xmm0 = mem[0],zero,zero,zero
    movss   %xmm0, 8(%rsp)          # 4-byte Spill
    movss   16(%rdi), %xmm3         # xmm3 = mem[0],zero,zero,zero
    movaps  %xmm3, 16(%rsp)         # 16-byte Spill
    movss   20(%rdi), %xmm0

然后再也不会引用%rdi(frustrum)内存。另一方面,引用和定义版本会根据需要加载值。

发生这种情况是因为Vector4构造函数的实现对优化器是隐藏的,并且不能假定构造函数不会修改frustrum,因此必须插入负载,即使此类负载是多余的。

因此,在某些情况下,天真版本甚至比“优化”版本还快。

关于c++ - 是否可以将编译时的 “reference”设置为变量?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38819841/

10-11 22:35
查看更多