Все временные значения r на С++?

Я занимаюсь кодированием на С++ в течение последних нескольких лет. Но есть один вопрос, который мне не удалось выяснить. Я хочу спросить, все ли временные в С++, rvalues?

Если нет, может ли кто-нибудь предоставить мне пример, где временный код в коде lvalue?

Ответы

Ответ 1

Нет.

Спецификация языка С++ никогда не делает такого простого утверждения, как тот, о котором вы просите. Он не говорит нигде в стандарте языка, что "все временные объекты являются rvalues". Более того, сам вопрос является немного неправильным, поскольку свойство быть rvalue на языке С++ не является свойством объекта, а скорее свойством выражения (т.е. Свойства его результата). Это на самом деле то, как оно определено в спецификации языка: для разных выражений он говорит, когда результат является значением lvalue и когда он является rvalue. Помимо всего прочего, это фактически означает, что к временному объекту можно получить доступ как значение r, так и lvalue, в зависимости от конкретной формы выражения, которая используется для выполнения доступа.

Например, результат выражения literal 2 + 3, очевидно, является rvalue, временным типом int. Мы не можем применить унарный & к нему, поскольку унарный & требует lvalue в качестве своего операнда

&(2 + 3); // ERROR, lvalue required

Однако, как мы все знаем, постоянная ссылка может быть привязана к временному объекту, как в

const int &ri = 2 + 3;

В этом случае ссылка привязана к временному, продлевая время жизни последнего. Очевидно, что как только это будет сделано, мы получим доступ к тому же временному, что и lvalue ri, так как ссылки всегда lvalues. Например, мы можем легко и юридически применить унарный & к ссылке и получить указатель на временный

const int *pi = &ri;

если этот указатель остается в силе до тех пор, пока сохраняется время.

Еще один очевидный пример доступа lvalue к временному объекту - это когда мы обращаемся к временному объекту типа класса с помощью его указателя this. Результатом *this является lvalue (как всегда бывает с результатом унарного *, применяемого к указателю данных), но это не меняет того факта, что фактический объект может быть легко временным. Для данного типа класса T выражение T() является rvalue, как явно указано в стандарте языка, но временный объект, доступ к которому через выражение *T().get_this() (с очевидной реализацией T::get_this()), является lvalue. В отличие от предыдущего примера, этот метод позволяет сразу получить не-const-квалифицированное значение lvalue, которое относится к временному объекту.

Итак, опять же, тот же самый временный объект может быть легко "замечен" как rvalue или как lvalue в зависимости от того, какое выражение (какой путь доступа) вы используете для "поиска" на этом объекте.

Ответ 2

Prasoon Saurav уже связал очень хорошую тему clС++. Там Джеймс Канзе объясняет, почему вопрос не имеет смысла. Это сводится к:

  • rvalue-ness - (логическое) свойство выражений - каждое выражение является либо lvalue, либо rvalue
  • временные выражения не являются выражениями

По этой причине вопрос не имеет смысла.

Хорошим примером является следующий код:

int main() {
  const int& ri = 4;
  std::cout << ri << std::endl; 
}

Временной int со значением 4 не является выражением. Выражение ri, которое напечатано, не является временным. Это lvalue, и относится к временному.

Ответ 3

Хорошо, что оператор массива возвращает ссылку, любая функция, возвращающая ссылку, может считаться одной и той же? все ссылки являются константами, в то время как они могут быть lvalues, они изменяют то, что они ссылаются, а не сами ссылки. то же верно для оператора *,

*(a temp pointer) = val;

Я клянусь, что использовал какой-то компилятор, который передавал временные значения любой функции, которая принимала ссылку,

чтобы вы могли пойти:

int Afunc()
{
   return 5;
}

int anotherFunc(int & b)
{
    b = 34;
}


anotherFunc(Afunc());

не может найти тот, который позволяет вам это сделать, однако ссылка должна быть const, чтобы разрешить передачу значений temp.

int anotherFunc(const int & b);

в любом случае, ссылки могут быть lvalues ​​и временными, трюк, являющийся ссылкой, которую он сам не модифицировал, только то, что он ссылается.

если вы считаете оператор -> как оператор, тогда временные указатели могут быть lvalues, но применяется одно и то же условие, а не указатель temp, который будет изменен, но то, на что оно указывает.

Ответ 4

Операция индексирования массива является временным и lvalue, что-то вроде [10] = 1 является примером того, что вы ищете; lvalue является временным, рассчитанным указателем.

Ответ 5

Это зависит от того, что вы считаете временной переменной. Вы можете написать что-то вроде

#include <stdio.h>
int main()
{
    char carray[10];
    char *c=carray+1;
    *(c+2+4) = 9;
    printf("%d\n",carray[7]);
    return 0;
}

Это работает в VisualStudios и GCC. Вы можете запустить код в codepad

Я рассматриваю (c + 2 + 4) значение r, хотя я хочу назначить ему. Когда я разыграю его, он станет lvalue. Так что да все временные значения - это значения. Но вы можете сделать rvalues ​​(таким образом, временным) в lvalue, разыменовывая его

Ответ 6

Короткий ответ: да, но я не буду приводить этот стандарт, потому что доказательство этого вопроса потребует решения всех временных времен. По определению временное имеет срок службы одного оператора, поэтому назначение вещей одному из них в лучшем случае будет плохим.

Интересный ответ: Копирование elision может сделать (часто делает) временный объект, идентичный объекту lvalue. Например,

MyClass blah = MyClass( 3 ); // temporary likely to be optimized out

или

return MyClass( 3 ); // likely to directly initialize object in caller frame

Изменить: как вопрос о том, есть ли в этих случаях какой-либо временный объект, в §12.8/15 упоминается

операция копирования может быть опущена путем конструирования временного объекта непосредственно в цель пропущенной копии

который указывает, что существует временный объект, который может быть идентичен lvalue.

Ответ 7

Если нет, может ли кто-нибудь предоставить мне пример, где временный код в коде является lvalue?

Следующий код связывает постоянную ссылку на временный объект типа const float, созданный компилятором:

int i;
const float &cfr = i;

Поведение "как будто":

int i;
const float __tmp_cfr = i; // introduced by the compiler
const float &cfr = __tmp_cfr;