LINUX.ORG.RU

Уточнение синтаксиса C++


0

0

Собственно появились недопонимания. Правильно ли я понимаю такие факты:

// Вызывается конструктор с параметром bla,
// при входе в функции, после выхода из не
// класс удолятеся.
User user("bla");

// Создаётся 2 объекта, user (и tmp1 например)
// В объект user копируется tmp1.
// В итоге 2 объекта
User user = User("bla");

// Создаётся 1 объект, и указатель копируется в него
// После выхода из функции удаляется автоматом
User* user = &User("bla");

// Создаётся 1 объект и сам никогда не удаляется вообще
User* user = new User("bla");

// Создаётся 6 статических объектов
User u1 = u2("text") + u3("text") + u4("text")

★★

>// Вызывается конструктор с параметром bla,
// при входе в функции, после выхода из не
// класс удолятеся.
User user("bla"); 

"функцию" замени на scope, т.е. блок

>// Создаётся 2 объекта, user (и tmp1 например)
// В объект user копируется tmp1.
// В итоге 2 объекта
User user = User("bla"); 

в случае агрессивной оптимизации объект может быть и один

>// Создаётся 1 объект, и указатель копируется в него
// После выхода из функции удаляется автоматом
User* user = &User("bla"); 

я могу ошибаться, но по-моему время жизни неименованного временного
объекта compiler-specific и стандартом не определено. при наличии
ссылки на него - существует пока существует ссылка, но с указателями
такое вряд ли прокатит

>// Создаётся 6 статических объектов
User u1 = u2("text") + u3("text") + u4("text")

сильно зависит от того, как реализован класс User (смотри expression
templates на предмет пользовательских оптимизаций)

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

>>User user = User("bla");

>в случае агрессивной оптимизации объект может быть и один

А если я не ошибаюсь, такая форма записи является обычной инициализацией и будет просто создан user с помощью конструктора User("bla"). Форма записи пришла из C и оставлена для совместимости.

Пруфлинк навскидку не дам, но при необходимости могу поискать.

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

>>User user = User("bla");

>А если я не ошибаюсь, такая форма записи является обычной инициализацией и будет просто создан user с помощью конструктора User("bla"). Форма записи пришла из C и оставлена для совместимости

int i = 5; ~ int i(5);

User user("bla"); ~ User user = "bla";

User user("bla"); !~ User user = User("bla");

впрочем, ждём пруфлинков

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

Последний вопрос: Такой вариант программирования практикуется? Или обычно это делается как-то по другому? Я про:

megaStr str1 = megaStr("str1") + megaStr("str2") + megaStr("str3")

Вообщем спасибо за помощь.

--- Ниже флейм ---

> реализован класс User

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

P.S. > "функцию" замени на scope, т.е. блок

Согласен, ошибся :-)

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

>Такой вариант программирования практикуется?

в смысле - использование конкатенации строк? практикуется, почему бы и нет. хотя в большинстве случае достаточно sprintf'а :)

>--- Ниже флейм ---

а в чём флейм-то?

>Буду перекуривать тему создания классов...

имей в виду - минздрав предупреждает

jtootf ★★★★★
()

1. Не удаляется. Говорят не "класс удаляется/создаётся", а "объект удаляется/создаётся". Объекты создаются по классам. Объекты классов. Класс сигарет, объекты - прима, беломорканал. Здесь прима создастся и не будет удаляться.

2. Два объекта создаваться не будет. Вызовется конструктор копирования User ( User& );, если он, конечно, не закрыт. Останется жить один объект.

3. Создаётся указатель, создаётся объект, адрес объекта копируется в указатель, объект удаляется, остаётся показывающий вникуда указатель.

4. Чтобы u2, u3, u4 "писать/юзать", их надо создать сначала )

http://ymap.org/

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

Способ практикуется. sprintf - в топку как угрозу безопасности и источник дыр.

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

/me заглядывает в стандарт

Да, действительно, ты прав -- это impl-specific.

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

>2. Два объекта создаваться не будет. Вызовется конструктор копирования User ( User& );, если он, конечно, не закрыт. Останется жить один объект.

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

>3. Создаётся указатель, создаётся объект, адрес объекта копируется в указатель, объект удаляется, остаётся показывающий вникуда указатель.

compiler-specific. в рамках одного блока временный объект будет существовать, во всяком случае GCC 3.4 ведёт себя именно так. за блоком - вряд ли. если была бы ссылка - существовал бы пока существует ссылка. если хочешь, могу процитировать стандарт

>http://ymap.org/

а это что ещё за пиар? ты блоггер dramele, что ли? ;)

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

> 4. Чтобы u2, u3, u4 "писать/юзать", их надо создать сначала )

Я описался, имел введу:

User u1 = User("usr1") + User("usr2") + User("usr3")

И рискну предположить, что меня поняли именно так.

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

>И рискну предположить, что меня поняли именно так.

кто не рискует, тот не пьёт шампанского: совершенно верно!

jtootf ★★★★★
()

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

Что касается того, когда именно удаляется объект. Неужели это так важно? Главное, что бы он не удалялся раньше чем нужно и но удалялся сам когда его уже не используют. (то есть вне области видимости)

Хотя оптимизация таких вырожений:

User user = User("bla");

Меня удивила, даже сказать обрадовала, но не более того.

Что касается strcpy, strlen и тп, я имею дело с UTF8 и UTF16. Так что, по сути, в string.h не вижу вообще никакого толку.

Вообщем ещё раз всем спасибо, за столь быструю реакцию!

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

1. User user = User("bla");

Как осуществляется преобразование типа const char* к типу User?

Варианты: Существует конструктор с аргументом const char*. Тогда просто вызывается этот конструктор.

> compiler-specific. в рамках одного блока временный объект будет существовать, во всяком случае GCC 3.4 ведёт себя именно так. за блоком - вряд ли. если была бы ссылка - существовал бы пока существует ссылка. если хочешь, могу процитировать стандарт

Если compiler-spec., то с чего вы пишете, что внутри блока будет существовать? Компайл же специфик. Может будет, а может и не будет.

А по логике - как только создастся, так сразу и подохнет. Т.к. у него нет имени и "держаться ему незачем". Кто-то правда взял его адрес, но компилятор написал варнинг "взят адрес временного объекта без имени". Компилятор хотел сказать "интересно, кому такой бред мог понадобиться, ведь я щас деструктор этого объекта сдесь вставлю".

А когда объекты удаляются - очень важно. Что-то важное может находиться в деструкторе в рассчёте на место удаления объекта.

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

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

> А по логике - как только создастся, так сразу и подохнет.

он не подохнет до тех пор пока полное выражение не будет вычислено.

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

>Варианты: Существует конструктор с аргументом const char*. Тогда просто вызывается этот конструктор.

а можно ещё вариантов, пожалуйста? o_O а тут как-то число множественное, а вариант-то как бы один...

>Если compiler-spec., то с чего вы пишете, что внутри блока будет существовать? Компайл же специфик. Может будет, а может и не будет.

я этого не гарантирую :) но опыт показывает, что бывает и так

>Т.к. у него нет имени и "держаться ему незачем"

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

>А когда объекты удаляются - очень важно

я с этим где-то спорил?

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

>>2. Два объекта создаваться не будет. Вызовется конструктор копирования User ( User& );, если он, конечно, не закрыт. Останется жить один объект.

implementation defined. Ссылку я дал. Копирования я присваивания вообще может не быть.

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

Если копирующий конструктор с аргументом требуемого типа (в данном случае const char*) не существует, не доступен, тогда все будут сосать, компилятор тогда всех поработит.

Сорри, я там злостно опечатался, не User ( User& ) (охренеть, опечаточка), а User ( const char* ). Никакой не исплементатион дефинед, нах. Стандарт бехавиор.

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

>Если копирующий конструктор с аргументом требуемого типа (в данном случае const char*)

ну перечитай это ещё раз, будь добр,- и пойди выспись, протрезвей, или ещё что там тебе нужно. а потом процитируй сюда пятдесят раз подряд определение копирующего конструктора. можно из стандарта, можно из любой книги по C++, хоть "для чайников"

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

>Нет там ссылки, там операция взятия адреса.

а я говорил что здесь она есть? повторяю: по стандарту неименованный временный объект может жить очень долго вот в таком случае. в противном случае время его жизни compiler-specific

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

то есть:

User user = User("bla");
User user("bla");
User user = "bla";

- три эквивалентные формы? кстати, можно пункт стандарта указать -
у меня его под рукой счас нет, дома гляну. пожалуйста :)

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

Нет. В первом и 3м случае будет вызываться User("bla"). Читать пункт 12.6.1 стандарта. Компиляторы, естественно, это дело оптимизируют и реально не вызывают конструктор копирования. Но если закрыть конструктор копирования, то будет облом на этапе компиляции.

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

нашёл-таки стандарт, почитал

в обоих случаях идёт initialization, только в одном direct, в другом copy. честно - ничего не понимаю

всю жизнь считал, что в случае инициализации, т.е. при объявлении переменной, выражения T i(5) и T i = 5 эквивалентны. у Дьюхерста это расписано, если не ошибаюсь. однако стандарт говорит вот так :(

в общем, буду смотреть

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

>В первом и 3м случае будет вызываться User("bla")

кстати, User("bla") будет вызываться во всех трёх случаях. в первом и третьем дополнительно будет вызываться User(const User &)

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

Да, я имел вииду User(const User &) конечно же :)

Reset ★★★★★
()

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

Так вот. Всё с начала.

1. User user("bla");

Какой ... удаляется? Ничто не удаляется, остаётся user, сконструированный конструктором User ( const char* );

2. User user = User("bla");

То же самое, что User user ("bla"); Незнаю, по стандарту ли, или компилятор так оптимизирует, но по количеству создающихся объектов и по всему происходящему - это равносильно написанию User ( const char* ); Бинарь на выходе аналогичен бинарю на выходе 1.

3. User* user = &User("bla");

Создаётся временный объект User конструктором User ( const char* ), после чего адрес этого временного объекта записывается в указатель user. Всё, выражение закончилось, созданные в нём временные объекты херятся фтопку.

4. User u1 = User( 1 ) + User( 2 ) + User( 3 )

Смотря что намутить с User::operator+
1. User User::operator+ ( User& );
---- 5 конструирований User.
2. User& User::operator+ ( User& );
---- 4 конструирования User.





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

>>кстати, User("bla") будет вызываться во всех трёх случаях. в первом и третьем дополнительно будет вызываться User(const User &)

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

1) User user = User("bla");

Конструирование, присваивание. Такая конструкция подпадает под 12.8 Copying class objects, пункт 15, и с большой вероятностью будет соптимизирована компилятором до прямого конструирования (ссылку я дал выше).

2) User user("bla");

Обычное конструирование.

3) User user = "bla";

12.3.1 Conversion by constructor, там же про explicit конструкторы

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

> после этого я понимаю, почему не хочу писать компилятор C++ :)

В компиляторе все просто. А вот юзать оный, пописывая на С++, очень даже проблемно.

В общем, С++ требует ресинтаксификации.

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

> С++ требует ресинтаксификации.

и декапитации с дефекацией

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

>В компиляторе все просто

подавился бубликом (с) Miguel

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