Как работает C ++ ссылка - PullRequest
       1

Как работает C ++ ссылка

2 голосов
/ 14 сентября 2011

После 15 лет работы в C ++ я обнаружил, что не совсем понимаю ссылки ...

class TestClass
{
public:
    TestClass() : m_nData(0)
    {
    }

    TestClass(int n) : m_nData(n)
    {
    }

    ~TestClass()
    {
        cout << "destructor" << endl;
    }

    void Dump()
    {
        cout << "data = " << m_nData << "  ptr = 0x" << hex << this << dec << endl;
    }

private:
    int m_nData;
};

int main()
{
    cout << "main started" << endl;

    TestClass& c = TestClass();
    c.Dump();

    c = TestClass(10);
    c.Dump();

    cout << "main ended" << endl;

    return 0;
}

// prints:
// main started
// data = 0  ptr = 0x0012FF54
// destructor
// data = 10  ptr = 0x0012FF54
// main ended
// destructor

Из этого теста я понимаю, что экземпляр TestClass создается в стеке (это правильно?) И инициализируется первым конструктором TestClass. Когда этот экземпляр выделен: когда загружена основная функция или выполнено присвоение ссылки? Когда он будет уничтожен?

После второго задания ссылки адрес объекта не изменяется. Означает ли это, что деструктор и конструктор применяются к одной и той же области памяти? Или память освобождается (динамически «в стеке») и снова выделяется?

Я знаю все о времени жизни объектов, выделенных из стека и кучи, их конструкторах и деструкторах. Но я не могу понять, что именно происходит в этой программе.

Edit: Спасибо всем. Я попытался воспроизвести в этом тесте другое (более сложное) поведение программы. Ваши комментарии помогли мне понять и мою ошибку, и другую программу, с которой я борюсь ...

Фиксированный код:

int main()
{
    cout << "main started" << endl;
    TestClass t;

    TestClass& c(t);
    c.Dump();

    c = TestClass(10);
    c.Dump();

    cout << "main ended" << endl;
    return 0;
}

Ответы [ 5 ]

5 голосов
/ 14 сентября 2011

Ваш код страдает от множества проблем и в конечном итоге не имеет смысла.Тем не менее, давайте пройдемся по нему.

1) Вы можете привязать временный объект только к ссылке const , увеличивая таким образом его время жизни:

const TestClass & c = TestClass();

2)нельзя использовать dump, потому что вы не объявили его const:

void Dump() const

3) Сказать c = TestClass() - это задание.Однако c теперь является ссылкой на const, которой нельзя присваивать, поскольку присваивание не является постоянным (по очевидным причинам).Давайте разберемся с этим:

const_cast<TestClass&>(c) = TestClass(10);

Теперь мы присвоили новое значение временно-расширенному объекту c, и все так, как и должно быть:

main started
data = 0  ptr = 0x0xbfa8219c
destructor
data = 10  ptr = 0x0xbfa8219c
main ended
destructor

Указатели одинаковы, потому что есть только один объект, а именно (временный) объект, на который ссылается c.Присвоение ему является хаком, который в целом не определил поведение, но для целей этой демонстрации нам это сойдет с рук.

Промежуточный деструктор - это второй временный TestClass(10).

2 голосов
/ 14 сентября 2011

1) вы не можете получить неконстантную ссылку на временный объект

2) в строке c = TestClass (10);оператор = (...) называется

2 голосов
/ 14 сентября 2011
TestClass& c = TestClass();

Это даже не скомпилируется!

Попытка привязать временную к неконстантной ссылке приведет к ошибке компиляции.

Однако вы можете связать временную ссылку с константой:

{
   const TestClass& c = TestClass();
   //use c 
   //....
}//<-------- the temporary will be destroyed here.

В этом случае срок действия временного элемента распространяется на срок действия ссылки, т. Е. Когда переменная ссылки выходит из области видимости, временный объект будет уничтожен, как показано выше.

2 голосов
/ 14 сентября 2011
TestClass& c = TestClass(); // TestClass() temporary doesn't persist beyond this expression.
c.Dump();

TestClass() создает временный объект, и вы не можете использовать его ссылку.

const TestClass& c = TestClass();

const квалификация продлевает время жизни создаваемого временного объекта до объема объекта c.

1 голос
/ 14 сентября 2011

Хороший способ - сравнить ссылки на указатели ... (ссылки обычно реализуются одинаково в сборке, как правило, с помощью регистра ebx). Основное отличие состоит в том, что после инициализации ссылка является постоянной ...

Однако линия const TestClass& c = TestClass(); параллельна const TestClass* const pc = &TestClass();, поэтому объект будет создан и уничтожен в стеке, компьютер будет по-прежнему иметь тот же адрес.

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