Я думаю, что, возможно, я придумал пример rvalue типа array

StackOverflow https://stackoverflow.com/questions/4058151

Вопрос

C++03 §4.2 N°1:
Значение lvalue или rvalue типа “массив из N T” или “массив с неизвестной границей из T" может быть преобразовано в значение типа “указатель на T.” Результатом является указатель на первый элемент массива.

Что долгое время сбивало меня с толку в этом утверждении, так это то, что я не совсем понимал, что будет означать rvalue типа array .То есть я не смог придумать выражение, типом которого был бы массив, а результатом - rvalue .Я читал это поток, который в основном задает тот же вопрос, и принятый ответ - "нет, нет rvalue типа array".Я думаю, что у меня просто может быть противоречие по этому поводу.

C++03 §5.2.5 N°4: (речь идет о выражении E1.E2)
Если E2 является нестатическим элементом данных, и тип E1 равен “cq1 vq1 X", а тип E2 равен “cq2 vq2 T”, выражение обозначает именованный элемент объекта, обозначенный первым выражением.Если E1 является значением lvalue, то E1.E2 является значением lvalue.

Я предполагаю, что в противном случае это rvalue (при условии, что E2 не является ссылкой, этот случай рассматривается §5.2.5 N°3) и следовательно...

struct A
{
   int a[4];
};
A f()
{
   A a;
   return a; 
}
int main()
{
   f().a; //I think this is an rvalue of array type...
}

Я вижу здесь два варианта:
Вариант 1: Я прав, ура, ура, круто.В данном случае вопрос заключается в следующем:есть ли другие примеры?
Вариант 2: Я ошибаюсь, в данном случае вопрос заключается в следующем:является ли это дефектом стандарта?

Я не знаю насчет 1, но я действительно сомневаюсь насчет 2, потому что, когда они говорят о преобразованиях функции в указатель, они упоминают только lvalues типов функций (очевидно, понимая, что таких rvalues нет).Так что весьма вероятно, что они думали о rvalues типов массивов.

Итак, в основном мой вопрос заключается в том, нашел ли я пример rvalue типа array, и если нет, пожалуйста, укажите допустимый, который, я твердо верю, существует.

Это было полезно?

Решение

Да, вы правы.Выражение представляет собой rvalue типа array.Это не дефект - комитет знает об этом, и это также было распространенной проблемой в C89, который допускает преобразование в указатели только для значений lvalues типов массивов.Как следствие, вы не смогли бы проиндексировать или разыменовать массив, подобный f().a.C99 исправил это, и у C ++ нет проблем с этим.

Обратите внимание, что независимо от того, является ли это rvalue или нет, это не зависит от того, обозначает ли выражение объект.В C ++ 03 случайно не указано, что выражение rvalue типа array обозначает объект.Это было исправлено в C ++ 0x автор: DR#450.

(очевидно, понимая, что таких значений не существует)

На самом деле существуют rvalues типов функций.Это происходит для нестатических функций-членов, обозначаемых выражением доступа к члену класса

struct A { void f(); };

/* A().f is an rvalue of type "void()" */
int main() { A().f(); }

Другие советы

Буква "А" - это rvalue.Массив внутри него - нет.Представьте себе случай, когда у вас есть цепочка методов для этого временного объекта - переменные внутри него работают для более чем одного вызова и возврата метода, и они могут передавать ссылки (действительные в течение всего срока действия цепочки) другим функциям.Эти функции не могут заранее знать, что они будут вызваны по rvalue.

В последней версии черновика вы можете перегружать функции на rvalue/ lvalue *this.Однако даже в этом случае ссылка на rvalue не преобразует содержимое того, что относится к rvalue, и я не совсем уверен, что КАКОЙ-ЛИБО компилятор в настоящее время поддерживает это, и я знаю, что MSVC этого не делает.

Фактически, используя decltype , вы можете легко определить, что компилятор называет этот массив значением lvalue .

Рассмотреть:

template<typename A, typename B> auto sum(A&& a, B&& b) -> decltype(std::forward<A>(a) + std::forward<B>(b)) {
    return std::forward<A>(a) + std::forward<B>(b);
}

Это то, для чего был предназначен decltype, и он наиболее определенно проводит различие между lvalues и rvalues.В качестве альтернативы, рассмотрите это:

int main()
{
    auto var = f().a;
}

Var - это значение int*.Это мгновенный сбой, так как f().a немедленно умирает.Не уверен в моем непосредственном мнении по этому поводу, но оно определенно не подходит для rvalue.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top