重载指针的rvalue / const左值

时间:2017-05-04 17:33:25

标签: c++ c++11 rvalue-reference

我使用的是gcc 4.8.4。

以下代码因第22行(​​显示)中的编译器错误而失败:

  

从'int * const'类型的表达式初始化'int *&&'类型的引用无效

为什么不使用square(ptr)的左值版本调用square

#include <iostream>
#include <memory>

int square(int* &&num) {
    std::cout << "rvalue" << std::endl;
    std::unique_ptr<int> x(num);
    const auto ptr = x.get();
    return square(ptr);  // this is line 22
}

int square(const int* &num) {
    std::cout << "lvalue" << std::endl;
    return (*num) * (*num);
}

int main() {
    std::unique_ptr<int> up(new int);
    *up = 5;
    std::cout << square(up.release()) << std::endl;
}

2 个答案:

答案 0 :(得分:3)

您有订单问题:

return square(ptr);

仅查看int square(int* &&num)声明且无效

而且int square(const int* &num)应该是int square(int*const &num)

Fixed version

答案 1 :(得分:1)

在第22行,范围中square()的唯一定义是采用右值引用的定义 - int square(int* &&)ptr是左值,因此错误消息解释了类型的差异。

如果交换函数定义的顺序以使int square(const int* &)也在范围内,您仍会得到相同的错误。那是因为你有一个指向可变int的指针,所以左值函数仍然不是候选者。

您可以更改它以接受对int:

指针的const引用
int square(int *const& num) {
    std::cout << "lvalue" << std::endl;
    return (*num) * (*num);
}

现在程序编译并运行。

显然,这可以简化为按价值接受num,但我猜你想要使用比int更重量级的东西。

重写示例

#include <iostream>
#include <memory>

int square(int *const& num) {
    std::cout << "lvalue" << std::endl;
    return *num * *num;
}

int square(int*&& num) {
    std::cout << "rvalue" << std::endl;
    std::unique_ptr<int> x(num);
    const auto ptr = x.get();
    return square(ptr);
}

int main() {
    auto up = std::make_unique<int>(5);
    std::cout << square(up.release()) << std::endl;
}

作为旁注,我试图避免使用unique_ptr::release() - 当它与接受裸指针所有权的C ++ 11之前的代码接口时很有用,但它很难推理它没有详细遵循代码。现代代码应该更喜欢传递智能指针:

int square(std::unique_ptr<int>&& x) {
    std::cout << "rvalue" << std::endl;
    const auto ptr = x.get();
    return square(ptr);
}

int main() {
    auto up = std::make_unique<int>(5);
    std::cout << square(std::move(up)) << std::endl;
}

在这里,square()将对其论证拥有所有权更加清楚。