C ++: постоянная ссылка на временный - PullRequest
2 голосов
/ 24 декабря 2010

Есть несколько вопросов о времени жизни постоянной ссылки на SO, но все же я не понимаю.

Является ли этот фрагмент кода действительным?

struct S
{
    const int &ref;
    S( const int &x ) : ref(x) { }
};

int main( )
{
    S s( 0 );
    // ...
    use( s.ref );
    // ...
    return 0;
}

Интуитивно я быскажем «нет», поскольку 0 должно истечь после того, как выражение (S s(0);) будет оценено.

Однако и GCC, и CLANG скомпилируют его нормально, без предупреждений, и valgrind не обнаружит ошибок времени выполнения.

Что мне не хватает в ссылках?

Ответы [ 5 ]

4 голосов
/ 24 декабря 2010

Мне кажется недействительным в соответствии с 12.2 / 4:

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

Временное хранилище доживает до тех пор, пока s не будет полностью созданоне до точки, где вызывается use.

2 голосов
/ 24 декабря 2010

Поскольку у других есть указатель, стандарт C ++ только заставляет компилятор сохранять временный 0 во время вызова конструктора.На практике gcc поддерживает временную работу функции main, в результате чего программа работает должным образом.По этой причине нет предупреждений или ошибок времени выполнения.

Но это работает только случайно.Не полагайтесь на это поведение.

1 голос
/ 24 декабря 2010

Вот еще один твик к вашему коду, на который жалуется даже valgrind:

#include <iostream>

struct S
{
    const int &ref;
    S( const int &x ) : ref(x) { }
};

S* foo()
{
    return new S(0);
}

int main( )
{
    S* s = foo();
    std::cout << s->ref << std::endl;
    return 0;
}

Обычно это помещает временный элемент в кадр стека функции foo, поэтому он уничтожается, когда эта функция возвращается.Это похоже на возврат адреса локальной переменной.

В других ответах указано, почему компилятору разрешено это делать, мой код является лишь иллюстрацией.

1 голос
/ 24 декабря 2010

Здесь следует отметить не const, а ссылку.Const - это просто инструмент для статического анализа.Вы должны быть осторожны со ссылками, потому что они могут кусаться.

int& f()
{
    int i = 2;
    return i;
}

Иногда компилятор достаточно умен, чтобы предупредить вас о проблемах, которые могут появиться во время выполнения, но иногда это не так.В любом случае у компилятора нет , чтобы предупредить вас об этом.

0 голосов
/ 24 декабря 2010

0 не временный, это буквальный. Попробуйте это небольшое изменение в вашей программе:

struct S 
{
    const int &ref;
    S( const int &x ) : ref(x) { }
};

int f()
{
    return 0;
}

int main( )
{
    S s( f() );
    // ...
    use( s.ref );
    // ...
    return 0;
}

Я думаю, что правило для ссылок на временные ссылки работает только для локальных переменных, а не для членов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...