class Vec3{
private:
float x, y, z;
public:
Vec3() = default;
Vec3(const float c) {x = c; y = c; z = c;}
static Vec3& normalize(Vec3& v) {/* normalize */ return v;}
};
Vec3 aaa = Vec3( 1.0f);
Vec3 bbb = Vec3::normalize( Vec3( 1.0f));
Vec3 ccc = Vec3::normalize( aaa);
我想编写将向量作为参数的函数,对它们进行一些处理并将它们作为引用返回。
在上面的代码bbb
中不会编译,因为它是对rvalue的非const引用。我不能使它成为const,因为normalize
需要修改对象。如果我使函数接受rvalue引用(Vec3&& v
),那么ccc
将不会编译,因为aaa
是左值。我是否可以在不写normalize
的两个版本的情况下完成这项工作?
(我对rvalue vs左值引用感到困惑,我不明白为什么someFunc(const Vec3& v)
会同时接受rvalues和lvalues,而非const版本不会被接受。 )
答案 0 :(得分:8)
你可以用一点开销来做到这一点。您不必编写两次规范化代码,但需要以不同方式处理返回,因为您不希望返回对右值的引用。
如果您有类似
的内容static Vec3& normalize(Vec3& v) {/* normalize */ return v;}
static Vec3 normalize(Vec3&& v) { return normalize(v);}
^ v is a lvalue here
现在,您可以将临时值转发到左值参考版本,然后按值返回,这样您就不会尝试引用可能不再存在的对象。
答案 1 :(得分:1)
我不明白为什么someFunc(const Vec3& v)会接受rvalues和lvalues,而非const版本则不接受。
因为标准禁止将rvalues绑定到非const lvalue ref。这与
中的问题相同const int& x = 1; // OK
int& y = 2; // error
似乎该标准试图保护您免受临时修改的影响。不幸的是,我无法给你更深入的解释。但你可以读到这个:
Why not non-const reference to temporary objects?
How come a non-const reference cannot bind to a temporary object?
当然最后&&
的确被发明了。所以我猜它更像是一个历史原因?