无法使函数接受rvalue和左值引用

时间:2017-06-01 14:11:25

标签: c++ code-duplication rvalue lvalue

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版本不会被接受。 )

2 个答案:

答案 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)

不,你不能。你必须使用两个版本。您可以将它们组合为@NathanOliver建议,但您仍需要两个版本。

  

我不明白为什么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?

当然最后&&的确被发明了。所以我猜它更像是一个历史原因?