为什么int []被视为右值?

时间:2015-03-21 16:41:08

标签: c++ arrays pointers

假设我有这个功能:

void f(int*& ptr) {
//do something
}

当我尝试做的时候:

int array[3] = {};
f(array); //fails to compile, error array is rvalue
int* p = array;
f(p); //compiles

为什么第一种情况会失败?数组是否与指针等效?

2 个答案:

答案 0 :(得分:7)

不,数组不等同于指针。

在第一种情况下,必须将数组转换为指针。转换的结果是 rvalue ,它无法绑定到非const 左值引用,因此出错。

在第二种情况下,p左值,表示正确类型的对象,因此函数调用成功。

答案 1 :(得分:2)

int* p = array;
f(p);     // compiles
f(array); // (this compiles too!)

数组等同于指针,但是有一个特殊的规则,当数组的名称传递给它时,数组的名称将被自动视为指向数组第一个元素的指针函数参数,或初始化指针时(int* p = arrayint* p = &array[0]的快捷方式)。

使用f(p)的示例并不有趣:您只是手动将指针传递给数组的第一个元素。


int array[3] = {};
f(array); //fails to compile, error array is rvalue

在这里,"特殊情况"我谈过要申请(因此名称array再次被视为&array[0]),但该函数接受int*&而不是int*。要理解为什么会失败,请考虑一下:

#include <string>

void baz1(std::string& str) {}
void baz2(const std::string& str) {}

int main()
{
    // baz1("hello world!");
    // ^ Doesn't compile, because converting string literal
    //   to std::string would result in a *temporary*, and you
    //   may not bind a temporary to a reference-to-non-const

    baz2("hello world!");
    // ^ OK, because baz2 takes a reference-to-const
}

或者,同样的问题:

void ecl(int& x) {}
void ipse(const int& x) {}

int main()
{
    // ecl(3);  // doesn't compile
    ipse(3);    // OK
}

所以我们可以这样修理你的程序:

void f(int* const& ptr) {}
//          ^^^^^

int main()
{
    int array[3] = {};
    f(array);  // compiles!
}