考虑以下代码:
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/