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