Взятие адреса временного объекта
§5.3.1 Унарные операторы, раздел 3
Результат одинарный & Оператор является указателем на свой операнд. Операндом должно быть lvalue или квалифицированный идентификатор.
Что именно означает "должен быть" в этом контексте? Значит ли это ошибочно брать адрес временного? Мне было просто интересно, потому что g++ только предупреждает меня, а comeau отказывается компилировать следующую программу:
#include <string>
int main()
{
&std::string("test");
}
g++ предупреждение: taking address of temporary
comeau ошибка: expression must be an lvalue or a function designator
Кто-нибудь имеет компилятор Microsoft или другие компиляторы и может протестировать эту программу, пожалуйста?
Ответы
Ответ 1
Слово "должно" на стандартном языке означает строгое требование. Итак, да, ваш код плохо сформирован (это ошибка), потому что он пытается применить оператор адреса к не-lvalue.
Однако проблема здесь не в попытке получить адрес временного. Проблема заключается, опять же, в принятии адреса не-lvalue. Временный объект может быть lvalue или non-lvalue в зависимости от выражения, которое создает это временное или обеспечивает доступ к этому временному. В вашем случае у вас есть std::string("test")
- функциональный стиль, отлитый от не ссылочного типа, который по определению создает не-lvalue. Отсюда ошибка.
Если вы хотите получить адрес временного объекта, вы могли бы обойти это ограничение, выполнив это, например
const std::string &r = std::string("test");
&r; // this expression produces address of a temporary
при этом возвращаемый указатель остается действительным до тех пор, пока существует временное. Существуют и другие способы юридического получения адреса временного объекта. Просто ваш конкретный метод оказывается незаконным.
Ответ 2
Когда слово "должно" используется в стандарте С++, это означает "нужно от боли смерти" - если реализация не подчиняется этому, она ошибочна.
Ответ 3
Это разрешено в MSVC с опцией устаревших /Ze (расширения). Это было разрешено в предыдущих версиях MSVC. Он генерирует диагностику с включенными предупреждениями:
предупреждение C4238: используется нестандартное расширение: класс rvalue используется как lvalue.
Если параметр /Za не используется (соблюдение совместимости ANSI), выполните следующие действия:
ошибка C2102: '&' требуется l-значение
Ответ 4
&std::string("test");
запрашивает адрес возвращаемого значения вызова функции (мы будем игнорировать как несущественный факт, что эта функция является ctor). У него не было адреса, пока вы его не присвоили. Следовательно, это ошибка.
Ответ 5
Стандарт С++ на самом деле является требованием к совместимым реализациям С++. В местах написано, чтобы различать код, который должны принимать согласованные реализации, и код, для которого соответствующие реализации должны давать диагностику.
Таким образом, в этом конкретном случае соответствующий компилятор должен дать диагностику, если будет принят адрес rvalue. Оба компилятора делают, поэтому они соответствуют друг другу в этом отношении.
Стандарт не запрещает создание исполняемого файла, если определенный ввод вызывает диагностику, то есть предупреждения являются допустимой диагностикой.
Ответ 6
Я не эксперт по стандартам, но это, безусловно, звучит как ошибка для меня. g++ очень часто дает предупреждение только для вещей, которые действительно являются ошибками.
Ответ 7
пользовательское преобразование
struct String {
std::string str;
operator std::string*() {
return &str;
}
};
std::string *my_str = String{"abc"};