c++ 在什么情况下 a[n] 是一个右值?

参考 https://en.cppreference.com/w... 下面,这一行:

xvalue
a[n], the built-in subscript expression, where one operand is an array rvalue;

那么什么是array rvalue呢?

参考 https://en.cppreference.com/w... 下面说到

对于 expr1[expr2]
When applied to an array, the subscript expression is an lvalue if the array is an lvalue, and an xvalue if it isn't (since C++11).

什么时候数组不是一个左值呢?

参考下面代码

struct S
{
    int iarr[10];
    int i;
    std::string sarr[10];
    std::string s;
};

S get() { return S{}; }

template<class T>
void foo(T&& v) {}

int main()
{
    foo(get().iarr[0]);//int&
    foo(get().i);      //int&&
    foo(get().sarr[0]);//std::string&
    foo(get().s);      //std::string&&
    return 0;
}

根据cppreference的说法:

  • get()返回的是prvalue
  • get().m应该是xvalue
  • get().m[n]xvalue吗?
阅读 2.6k
2 个回答

简单的,(int[3]){1,2,3}此时这个就是一个右值数组,下标访问返回的为右值(xvalue),但通过偏移间接寻址后得到的恒为左值(以上写法在gcc和clang下正确),还有种写法为using arryTY = int[3];arryTY{1,2,3}

#include <iostream>
#include <type_traits>
#include <typeinfo>
using namespace std;


struct S
{
    int iarr[10];
    int i;
    std::string sarr[10];
    std::string s;
};

S get() { return S{}; }

std::string sarr[10];

template<class T>
void foo(T&& v) {}
/*
decltype

a) 若 expression 的值类别为亡值,则 decltype 产生 T&& ;
b) 若 expression 的值类别为左值,则 decltype 产生 T& ;
c) 若 expression 的值类别为纯右值,则 decltype 产生 T 。
若 expression 是返回类类型纯右值的函数调用,或是右运算数为这种函数调用的逗号表达式,则不对该纯右值引入临时量。

(C++17 前)
若 expression 是(可有括号的)立即调用以外的 (C++20 起)纯右值,则不从该纯右值实质化临时对象。

(C++17 起)
类型不需要完整或拥有可用的析构函数,而且能为抽象。此规则不应用到子表达式: decltype(f(g())) 中, g() 必须有完整类型,但 f() 不必。

*/
int main()
{
    cout<<is_rvalue_reference_v <decltype(get().iarr[0])><<endl;//true ->xvalue
    cout<<is_rvalue_reference_v <decltype(get().i)><<endl;
    cout<<is_rvalue_reference_v <decltype(get().sarr[0])><<endl;//true ->xvalue
    cout<<is_rvalue_reference_v <decltype(get().s)><<endl;
    cout<<is_rvalue_reference_v <decltype(get())><<endl;
    cout<<is_rvalue_reference_v <decltype(get().iarr)><<endl;
    cout<<is_rvalue_reference_v <decltype(get().sarr)><<endl;
cout<<endl;
    cout<<is_lvalue_reference_v <decltype(get().iarr[0])><<endl;
    cout<<is_lvalue_reference_v <decltype(get().i)><<endl;
    cout<<is_lvalue_reference_v <decltype(get().sarr[0])><<endl;
    cout<<is_lvalue_reference_v <decltype(get().s)><<endl;
    cout<<is_lvalue_reference_v <decltype(get())><<endl;
    cout<<is_lvalue_reference_v <decltype(get().iarr)><<endl;
    cout<<is_lvalue_reference_v <decltype(get().sarr)><<endl;


     
    return 0;
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题