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