Подтвердить что ты не робот

Ссылка Rvalue обрабатывается как Lvalue?

Я отправил этот ответ: qaru.site/info/279202/... который содержит следующий код:

void foo(string&& bar){
    string* temp = &bar;

    cout << *temp << " @:" << temp << endl;
}

Является ли bar значением r или lvalue?

Я спрашиваю, потому что я, очевидно, не могу взять адрес rvalue, но я могу взять адрес ссылки rvalue, как это делается здесь.

Если вы можете выполнить любую операцию над ссылкой rvalue, которую вы можете использовать для ссылки lvalue, какая точка в дифференциации между двумя с помощью "& &" а не просто "&"?

4b9b3361

Ответ 1

Является ли bar значением rvalue или lvalue?

Вопрос отвечает сам. То, что имеет имя, - это lvalue (1). Таким образом, bar является lvalue. Его тип "rvalue reference to string", но это lvalue этого типа.

Если вы хотите рассматривать его как rvalue, вам нужно применить к нему std::move().


Если вы можете выполнить любую операцию над ссылкой rvalue, которую вы можете использовать для ссылки lvalue, какая точка в дифференциации между двумя с помощью "& &" а не просто "&"?

Это зависит от вашего определения "выполнить операцию". Ссылка на lvalue и ссылочную ссылку (named) rvalue в значительной степени идентичны в том, как вы можете использовать их в выражениях, но они сильно различаются в том, что может связываться с ними. Lvalues ​​могут связываться с lvalue-ссылками, rvalues ​​могут связываться с rvalue-ссылками (и что-либо может связываться с ссылкой lvalue на const). То есть вы не можете привязать rvalue к ссылке lvalue или наоборот.

Расскажите о параметре функции ссылочного типа rvalue (например, ваш bar). Важным моментом является не то, что bar, но то, что вы знаете о значении, к которому относится bar. Поскольку bar является ссылкой на rvalue, вы наверняка знаете, что любая связанная с ним функция была rvalue. Это означает, что он должен быть уничтожен, когда заканчивается полное выражение, и вы можете спокойно относиться к нему как к rvalue (путем кражи его ресурсов и т.д.).

Если вы не делаете это непосредственно с bar, но просто хотите передать bar on, у вас есть два варианта: либо вы закончили с bar, а затем вы должны сообщить следующее тот, кто получает его, что он привязан к rvalue, do std::move(bar). Или вам нужно сделать еще несколько вещей с помощью bar, и поэтому вы не хотите, чтобы кто-либо из них крал свои ресурсы из-под вас, поэтому просто рассматривайте его как lvalue — bar.

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


(1) Хорошее эмпирическое правило, за небольшими исключениями: перечисления имеют имена, но являются значениями r. Классы, пространства имен и шаблоны классов имеют имена, но не являются значениями.

Ответ 2

Является ли строка rvalue или lvalue?

Это lvalue, как любое выражение, которое называет переменную.

Если вы можете выполнить любую операцию над ссылкой rvalue, которую вы можете использовать для ссылки lvalue, какая точка в дифференциации между двумя с помощью "& &" а не просто "&"?

Вы можете инициализировать только ссылку rvalue с помощью выражения rvalue. Таким образом, вы можете передать временную строку в свою функцию, но вы не можете передать строковую переменную без явного перехода от нее. Это означает, что ваша функция может считать, что аргумент больше не нужен, и может перейти от него.

std::string variable;
foo(variable);            // ERROR, can't pass an lvalue
foo(std::move(variable)); // OK, can explicitly move
foo("Hello");             // OK, can move from a temporary

Ответ 3

Здесь в этом случае с именем rvalue ссылаются lvalues ​​, а если тип ввода const с именем rvalue references, то он будет rvalue, вот простой пример:

#include <string>
#include <iostream>

void foo(const std::string&& bar) { 
    std::string* temp = &bar; // compile error, can't get address
    std::cout << *temp << " @:" << temp << std::endl;
}

int main()
{
    foo("test");
    return 0;
}

Надеюсь, это полезно.

Ответ 4

bar выражения является lvalue. Но это не "ссылка на строку". bar выражения является ссылкой lvalue. Вы можете проверить это, добавив следующую строку в foo():

cout << is_lvalue_reference<decltype((bar))>::value << endl; // prints "1" 

Но я согласен с остальными объяснениями Ангела.

Ссылка rvalue после того, как она привязана к rvalue, является ссылкой на lvalue. На самом деле это не только параметры функции:

string&& a = "some string";
string&& b = a; // ERROR: it does not compile because a is not an rvalue

Если вы можете выполнить любую операцию над ссылкой rvalue, которую вы можете использовать в справочной системе lvalue, какая разница между двумя с помощью "&&" вместо "&"?

Ссылка rvalue позволяет нам выполнять некоторые операции "lvalue" до истечения времени rvalue.