LINUX.ORG.RU

ссылки + указатели в Qt

 


0

2

Объявление, к примеру, QLabel:

explicit QLabel(const QString &text, QWidget *parent=0, Qt::WindowFlags f=0);

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

В чем профит от использования внутри функции QString-a по ссылке, а parent-a по указателю ?



Последнее исправление: vux (всего исправлений: 2)

В чем профит от использования внутри функции QString-a по ссылке, а parent-a по указателю ?

Не бывает нулевой ссылки.

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

я понимаю разницу. Я не понимаю почему QString передается по ссылке, а parent по указателю в одной функции. В чем разница, если разрабы Qt рекомендуют использовать именно указатели?

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

У тебя же в объявлении записаны параметры по умолчанию. Первый аргумент обязателен, остальные нет. Если необязательные параметры не переданы, им будут присвоены значения по умолчанию, из объявления.

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

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

----

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

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

Я вон написал выше очень длинно.

Но если коротко то, потому что число 0 занимает в памяти меньше места, чем сконструированная «пустая балванка» QWidget.

hibou ★★★★★
()

В чем профит от использования внутри функции QString-a по ссылке, а parent-a по указателю ?

ссылка не может указывать в никуда, это не имеет смысла. Ссылка _всегда_ связана с объектом(потом у синтаксически можно использовать ссылку как объект, что даёт возможность писать функции(операторы), которые ведут себя синт аксически как объекты. К примеру можно сделать operator[](), который проверяет границы массива).

Указатель может указывать в никуда, и тогда(и только тогда) он имеет значение NULL (в C++ это тоже самое, что 0).

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

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

на само деле — означает. Однако вовсе не обязательно, что «строка» это непрерывный кусок памяти с char'ами внутри. В принципе это может быть что угодно.

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

Мы про данный конкретный случай. И так было понятнее, мне так казалось. Мы об одном и том же говорим, только разными словами. :)

Ссылкой ты передаешь ссылку на объект, который хранит в себе указатель на реальную строку в памяти. Если то же самое передать объектом, то получится, что передаешь объект, который в себе содержит указатель на ту самую строку. Разница конечно есть, но не такая большая как если бы прям реально строка копировалась бы.

hibou ★★★★★
()
Последнее исправление: hibou (всего исправлений: 2)
Ответ на: комментарий от hibou

я не спорил, а дополнил.

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

фишка в том, что строки может вообще не существовать. Это может быть например связанный список букв/слов. Или ещё что-нибудь, что пожелает разработчик класса. При этом внутреннее представление может и измениться со временем. Однако в клиентском коде так и останется неизменная ссылка на QString.

Причина, по которой в данном случае передаётся именно ссылка, а не сам объект, заключается больше в том, что это _константная_ ссылка, т.е. данный метод никак не изменяет этот text. По этой причине более логично передать ссылку на text, а не сам text.

Ну а с parent вариантов нет, тут нужно обязательно передать указатель, т.к. бывают виджеты без parent'а (не, ну можно конечно сделать фиктивный объект NIL, но бритва Оккама).

emulek
()

что бы можно было вызвать функцию только с одним кустрингом QString text; QLabel(text); а если бы все были ссылки, то нужно было бы передавать и все остальные параметры учите язык мать вашу

anonymous
()

В чем профит от использования внутри функции QString-a по ссылке, а parent-a по указателю ?

С константной ссылкой можно написать так:

QLabel label = new QLabel( "текст тут" );

С указателем тебе придётся делать так:

QString text( "текст тут" );
QLabel label = new QLabel( &text );

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

Я не понимаю почему QString передается по ссылке, а parent по указателю в одной функции.

В Qt все виджеты выстраиваются в иерархическую структуру. В этом месте удобно исспользовать указатели. Т е виджеты содержат в себе указатели на родителя и потомков.

А вот строку QLabel копирует к себе во внутрь. Т е эта строка не шарится между экземпляром QLabel и внешним миром. Вот по этой причине укзатель тут как бы ненужен. Ну а по значению передавать - это типа лишние расходы. Вот и юзают ссылку.

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

С константной ссылкой можно написать так

Наркоман? Зачем писать о том, чего не знаешь? Подачи кресты, прежде чем кого-то учить.

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

Ты получил UB до того, как получил text2. Так что не аргумент.

А по существу есть что сказать анонимный ты наш.

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

Наркоман? Зачем писать о том, чего не знаешь? Подачи кресты, прежде чем кого-то учить.

Уровень твоих знаний для всех стал очевиден. Давай до свидания!

dnf83
()

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

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

Если факт использования UB не является для тебя «существенным», то я вообще слабо представляю, что же тогда существенно

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

Еретик! Поклонись писанию и гуглу — пророку его!

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

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

это не самая лучшая практика, т.к. указатель менее надёжен и менее безопасен, чем ссылка. Лучше передавать по неконстантной ссылке то, что может быть изменено. А указатель есть смысл использовать лишь для таких параметров, которые могут принимать значение NULL (nullptr).

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

как ответил ктото на progs.org.ru:

из офф. доки: We do not recommend holding pointers to child objects from outside the parent.

Это значит, что экземпляры классов, наследованные от QObject следует передавать по указателю. Иначе, если прочитаете документацию более подробно, рано или поздно ваше приложение потерпит крах.

Таким образом остальные объекты, которые не наследованы от QObject, лучше всего передавать по классической схеме в виде ссылок, для обеспечения лучшей оптимизации кода компилятором.

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

Английский текст не совпадает с переводом )

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

Если факт использования UB не является для тебя «существенным», то я вообще слабо представляю, что же тогда существенно

И к чему ты это написал? Человек приводил аргумент, что ссылка не может быть в никуда. Я привёл пример такой ссылки. Какая разница UB это или не UB? То что это UB тебя как-то спасёт от падения программы?

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

Одну?

Одну, две, по существу моего ответа есть что сказать?

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

То что это UB тебя как-то спасёт от падения программы?

Тут дело не в «спасении». А в соглашениях. Можно сделать параметр указателем, потом написать в документации/комментариях, что он не может быть нулевым. И ещё асерт добавить. А можно использовать ссылку. Вменяемым людям это сразу достаточно скажет.

И таки-да, УБ - это плохо и тогда гарантий уже никаких нет.

DarkEld3r ★★★★★
()

Унылости тред.

Можно так… можно не так… нельзя так… нет можно.

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

Человек приводил аргумент, что ссылка не может быть в никуда. Я привёл пример такой ссылки. Какая разница UB это или не UB?

UB это хрень, а не аргументация.

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

Ты всегда такой зануда? Ну забыл я там звёздочку, это проблема для тебя?

проблема. Я просто не понял, что ты этим хотел сказать. Попробуй ещё раз.

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

В данном конкретном случае, что по ссылке, что без нее, разницы почти нет

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

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

не только я, но и наш компилятор.

Передавай привет вашему компилятору.

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

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

Не весь QString. QString как и std::basic_string<> использует внутри copy-on-write. Т.е. сама строка с текстом будет скопирована только при записи в нее.

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

т.е. весь QString все-равно будет скопирован.

AFAIK QString не содержит строки, а только указатель на неё. Потому разницы почти нет, т.к. QString весит почти столько-же, сколько и ссылка. Даже если размер строки 100500 килобайт.

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

Да, в нем нет строки, а только указатель на нее, однако при передачи аргумента в функцию по значению, сама функция должна иметь точную копию объекта. Согласен, что на стек это никак не повлияет, но операция копия все-равно произойдет

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

но операция копия все-равно произойдет

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

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