【问题标题】:Overloading rvalue/const lvalue for pointer为指针重载右值/常量左值
【发布时间】:2017-05-04 17:33:24
【问题描述】:

我使用的是 gcc 4.8.4。

以下代码失败,第 22 行出现编译器错误(已指示):

从“int* const”类型的表达式中对“int*&&”类型的引用的初始化无效

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

#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;
}

【问题讨论】:

  • square(const int* &amp;) 是否在 square(int*&amp;&amp;) 之前前向声明?如果不是,则square(int*&amp;&amp;) 不知道square(const int* &amp;) 存在,因此尝试递归调用自身,因为const int* 不能分配给int*&amp;&amp;

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


【解决方案1】:

您有订单问题:

return square(ptr);

只看到int square(int* &amp;&amp;num)声明并且无效

int square(const int* &amp;num) 应该是 int square(int*const &amp;num)

Fixed version.

【讨论】:

  • const int*int* const 是两个不同的东西。第一个是指向 const int 的非常量指针,第二个是指向非常量 int 的 const 指针。
【解决方案2】:

在第 22 行,square() 在范围内的唯一定义是采用右值引用的定义 - int square(int* &amp;&amp;)ptr 是一个左值,所以错误信息解释了类型的不同。

如果您交换函数定义的顺序以使int square(const int* &amp;) 也在范围内,您仍然会得到相同的错误。那是因为你有一个指向可变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() 将拥有其参数的所有权更加清楚。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-22
    • 1970-01-01
    • 2015-06-01
    • 1970-01-01
    相关资源
    最近更新 更多