【发布时间】:2016-02-10 12:51:29
【问题描述】:
考虑以下两个简单 Matrix4x4 Identity 方法的实现。
1:这个以Matrix4x4引用为参数,数据直接写入其中。
static void CreateIdentity(Matrix4x4& outMatrix) {
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
outMatrix[i][j] = i == j ? 1 : 0;
}
}
}
2:这个返回一个 Matrix4x4 而不接受任何输入。
static Matrix4x4 CreateIdentity() {
Matrix4x4 outMatrix;
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
outMatrix[i][j] = i == j ? 1 : 0;
}
}
return outMatrix;
}
现在,如果我想真正创建一个身份矩阵,我必须这样做
Matrix4x4 mat;
Matrix4x4::CreateIdentity(mat);
对于第一个变体和
Matrix4x4 mat = Matrix4x4::CreateIdentity();
第二次。
第一个显然产生了一个优点,即没有完成一个不必要的副本,同时它不允许将其用作右值;想象一下
Matrix4x4 mat = Matrix4x4::Identity()*Matrix4x4::Translation(5, 7, 6);
最后一个问题:有没有办法在尽可能使用Matrix4x4::CreateIdentity(); 之类的方法时避免不必要的复制,同时仍然允许像我上一个代码示例中那样将该方法用作右值?它甚至由编译器自动优化吗?我很困惑如何有效地完成这个(看似)简单的任务。也许我应该实现这两个版本并使用任何合适的版本?
【问题讨论】:
-
至少还有另一种避免复制的方法,即在语法上不那么尴尬:通过
std::move返回,并在您的类中定义移动构造函数和移动赋值运算符。 -
@VioletGiraffe 我认为一个简单的返回应该已经使用了适用的移动构造函数,即
select the constructor to use for initialization of the returned value is performed twice: first as if expression were an rvalue expression (thus it may select the move constructor or a copy constructor taking reference to const)。但我不确定这是否始终如我所见。想法? -
@VioletGiraffe 我记得,我曾经收到一个关于既没有移动也没有复制构造函数的对象的警告,警告是“注意,如果 NRVO 没有,这将不起作用发生在这里。”但这里不是这样。那么再一次,想法?
-
@VioletGiraffe 如果您使用
std::move,则不会发生 NRVO,如果我没记错的话,生成的代码可能会降低效率。