LINUX.ORG.RU

Ссылки в С++


0

0

Вопрос: Создание ссылки на временную переменную (и вообще на временную переменную) как-то влияет на время жизни целевого объекта? Например:
int& c = i*20;
результат вычисления i*20 это временная переменная, которая по идее должна исчезать после использования данного выражения (на следующей строке программы грубо говоря этой временной переменной уже быть не должно), создание подобной ссылки продлевает жизнь такой переменной превращая её в реальный lvalue или нет?

Ответ на: комментарий от Demon37

Что очень логично.

Правда есть еще одна нелогичная тема. А именно:
int i = 0;
const int& r = i;
i++;
Чему будет равно r? Ответ: 1. Собственно вопрос: константная ссылка может указывать на неконстантный объект и объект на который указывает такая ссылка может изменяться логично это (или правильно ли это)?

Указатель на константный объект себя ведет также (имею ввиду const int* p = &i), но для указателей такое поведение логично и правильно. А для константных ссылок далеко не очевидно ибо существуют правила по которым при инициализации константной ссылки могут проходить преобразования типов с созданием временной переменной, которая становится инициализатором и её нельзя изменить и пр. В итоге получается фифти/фифти толи константная ссылка действительно будет константной либо нет. Нет единой семантики, гарантирующей константность объекта, и это мне кажется неверным.

mskmsk1985
() автор топика
Ответ на: комментарий от mskmsk1985

>Собственно вопрос: константная ссылка может указывать на неконстантный объект и объект на который указывает такая ссылка может изменяться логично это (или правильно ли это)?

Собственно мне кажется это логичным. Т.к. изменяется-то не ссылка, а то, на что она ссылается. Главное то, что r может быть ссылкой только на i и ни на какую другую переменную.

Demon37 ★★★★
()

Ответ:

Учитывая, что ссылку можно инициализировать только при обьявлении, переменная на которую ссылается ссыслка имеет время жизни как минимум такое же.

Conficker
()
Ответ на: комментарий от Conficker

Да пример неудачный так как не компилируемый вообще. Язык не позволяет устраивать не константные ссылки на временные переменные.

mskmsk1985
() автор топика
Ответ на: комментарий от Demon37

Да но при небольшом несовпадении типов:
short i = 0;
const int& r = i;
i++;
будет осуществлено продвижение и создана временная переменная и именно ею будет проинициализированна r, и в этом случае константность объекта на который ссылается ссылка гарантирована. Тоже будет если исходный объект будет unsigned int а ссылка const int&. Идея в том что даже малейшие расхождения типов приводят к гарантии константности объекта, которая не гарантируется только если типы полностью идентичны (что формально говоря не верно, так как что const что unsigned модифицируют интегральный тип int, так почему модификатор типа unsigned сказывается на гарантии константности ссылки, а модификатор типа const нет? Получается что среди равных есть те кто равнее...). По-моему это очень тонкое и не очевидное место с очень скользкой семантикой! Руководствуясь тем, что семантика в языке должна быть одна хочется сказать что такое поведение не правильно.

mskmsk1985
() автор топика
Ответ на: комментарий от mskmsk1985

> и в этом случае константность объекта на который ссылается ссылка гарантирована.

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

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от mskmsk1985

#include <iostream>
// output: i=2 j=2

int main()
{
    int i=1;
    const int& j=i;
    i=2;
    // j=3;  // double-access.cxx:9: error: assignment of read-only reference ‘j’
    std::cout << "i=" << i << " j=" << j << '\n';
    return 0;
}

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от mskmsk1985

> Руководствуясь тем, что семантика в языке должна быть одна хочется сказать что такое поведение не правильно.

А еще есть нити, там значение по констовой ссылке может неожиданно поменяться.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

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

mskmsk1985
() автор топика
Ответ на: комментарий от Demon37

При этом у вас a = b (после c = b), а c это ссылка на a и ни на что иное! После инициализации ссылка становится синонимом того lvalue которое её инициализирует и все операции с ссылкой совершаются над этим lvalue. В чем ерунда?

mskmsk1985
() автор топика
Ответ на: комментарий от Demon37

. . .

int & c = a; // присваивается адрес

. . .

c = b; // присваивается значение &c != &b

std::cout << a << endl; // будет 3

Conficker
()
Ответ на: комментарий от www_linux_org_ru

Так об сим и речь. Если есть нити и некая функция то и при её вызове где-то совершается легкое преобразование типов а где-то нет ... где-то функция работает нормально (где создалась временная переменная и константная ссылка это константная ссылка), а где-то ... долго в отладчике с кофем и иными крепкими напитками сидеть будем. И что это - гибкость языка или эротичное место в семантике языка? Я за второе ибо int и const int это РАЗНЫЕ типы и раз есть правило о том, что при несовпадении типов создается временная переменная для инициализации константной ссылки, то почему тут от этого правила отказались? Где единство семантики языка?

mskmsk1985
() автор топика
Ответ на: комментарий от mskmsk1985

>При этом у вас a = b (после c = b), а c это ссылка на a и ни на что иное! После инициализации ссылка становится синонимом того lvalue которое её инициализирует и все операции с ссылкой совершаются над этим lvalue.

Признаю, ступил.

Demon37 ★★★★
()
Ответ на: комментарий от mskmsk1985

> И вопрос в том нужно ли давать такую гарантию на все или нет.

Однозначно не нужно.

______________________________________________

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

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от mskmsk1985

#include <iostream>

short i = 0; 
long long I=0;
/*
    very
    much
    code
    here
*/
int main()
{
    const long long& r = i; 
    i++;     
    std::cout << "i=" << i << " r=" << r << '\n'; // output: i=1 r=0
    const long long& R = I;
    I++;
    std::cout << "I=" << I << " R=" << R << '\n'; // output: I=1 R=1
    return 0;
}

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

способ применения грабель:

1. вначале long long i = 0; и все хорошо работает

2. поменять на short i = 0;

3. удивляться, почему програ заглючила.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

Слишком категорично. Если б было столь однозначно никто бы эту тему не поднимал. Хотя по факту голая риторика, а грабли действительно есть!

mskmsk1985
() автор топика
Ответ на: комментарий от mskmsk1985

> Слишком категорично. Если б было столь однозначно никто бы эту тему не поднимал.

Хорошо, объясни, как ты видишь гарантии. Можешь придумать новое ключевое слово.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

Пока язык не обеспечивает гарантий пример с ними написать очевидно нельзя. А насчет как должно было бы быть то все просто: при инициализации константной ссылки неконстантной переменной создавать временнцю переменную помещать туда текущее значение переменной и ииспользовать даннуб временнуб переменнуб как инициализатор константной ссылки (вообще инициализировать константные ссылки только времнными перемнными). Минус очевиден - появляется коприрование объектов при инициализации константных ссылок, что отражается на производительности (аргументы функций), что неприемемо для с++, и потому так не было и не будет никогда сделано. Вывод: с++ никогда не будет языком с однозначной и простой семантикой, так что следите за граблями господа!

mskmsk1985
() автор топика
Ответ на: комментарий от mskmsk1985

> А насчет как должно было бы быть то все просто: при инициализации константной ссылки неконстантной переменной создавать временнцю переменную помещать туда текущее значение переменной и ииспользовать даннуб временнуб переменнуб как инициализатор константной ссылки (вообще инициализировать константные ссылки только времнными перемнными).

А зачем тогда *вообще* ссылка? Просто пишешь const int a=b; и имеешь все гарантии.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от mskmsk1985

> Вывод: с++ никогда не будет языком с однозначной и простой семантикой, так что следите за граблями господа!

Как страшно жить...

Дело не в языке, а в том, что сам вопрос гарантий не простой. Есть разные решения.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

Что впрочем не вызывет никаких сомнений.

ЗЫ: была мысль про COW поедение для объекта на который указывает константная ссылка при его изменении, однако сколь такое возможно в языке общего назначения и высого уровня я пока не знаю.

mskmsk1985
() автор топика
Ответ на: комментарий от mskmsk1985

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

ЕМНИП для строк его делают, и более общий вариант можно и обсудить.

Заодно -- интел выпустила с++ STM complier v.3.0, только что докачал (аж 500 МБ). http://www.linux.org.ru/view-message.jsp?msgid=3705184

www_linux_org_ru ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.