K>>Исполнение этого кода, скомпилированного VC 7.1, приводит к выводу двух строк "Destructor was called". K>>А если раскомментировать явное определение default constructor, то одной строки. K>>Почему так?
Fox>Хотите еще веселее ??? Fox>Попробуйте деструктор сделать виртуальным Fox>Будет один раз срабатывать.
Ну если бы он еще и при виртуальном деструкторе копию создавал, тогда бы вообще повеситься можно.
Здравствуйте, kvas, Вы писали:
K>Исполнение этого кода, скомпилированного VC 7.1, приводит к выводу двух строк "Destructor was called". K>А если раскомментировать явное определение default constructor, то одной строки. K>Почему так?
Достаточно выводить адрес объекта, чтобы понять картину.
В первом случае создаётся и убивается временный объект, а объект по ссылке (кстати, можно и без ссылки, а просто!)
Foo f = Foo();
создаётся конструктором копирования и убивается по выходу из блока.
Во втором случае — обходятся без промежуточного объекта.
Инициализация присваиванием может проходить по двум сценариям: конструирование как есть и копирование.
Оба варианта равноправны и отдаются компилятору.
Вообще же, если класс CopyConstructible и Assignable, то побочные эффекты (здесь — вывод в консоль) в конструкторах, деструкторе и присваивании лучше не делать. Потому что иначе получается unspecified / implementation-defined behaviour, то есть — как повезёт.
Здравствуйте, Кодт, Вы писали:
К>Вообще же, если класс CopyConstructible и Assignable, то побочные эффекты (здесь — вывод в консоль) в конструкторах, деструкторе и присваивании лучше не делать. Потому что иначе получается unspecified / implementation-defined behaviour, то есть — как повезёт.
Это вывод из отдельных положений стандарта или там есть отдельный пункт с таким утверждением?
Здравствуйте, Mr. None, Вы писали:
MN>Здравствуйте, jazzer, Вы писали:
MN>>>Нет никакого глюка.
MN>>>В первом случае создаётся ещё один временный объект — вот и 2 вызова деструктора: 1-ый для Foo() (вызывается когда завершается инициализация ссылки), 2-ой для временного объекта созданного компилятором и связанного с сылкой (вызывается когда уничтожается ссылка). MN>>>Во втором случае компилятор непосредственно связывает временный объект, созданный вызовом Foo() с сылкой и удерживает его до уничтожения ссылки — деструктор вызывается один раз.
MN>>>По стандарту компилятор может поступать и так и эдак, причём делает это он на своё усмотрение.
J>>А можно ссылочку? J>>Что-то я не помню разрешения плодить временные объекты
MN>Стандарт — 8.5.3/4, 12.2/1, 12.2/5 ;)
Здравствуйте, UGN, Вы писали:
К>>Вообще же, если класс CopyConstructible и Assignable, то побочные эффекты (здесь — вывод в консоль) в конструкторах, деструкторе и присваивании лучше не делать. Потому что иначе получается unspecified / implementation-defined behaviour, то есть — как повезёт.
UGN>Это вывод из отдельных положений стандарта или там есть отдельный пункт с таким утверждением?
Отдельного пункта нет. Однако же, если ты не можешь, исходя из синтаксиса, утверждать — сколько раз и в каком порядке будет выполнена некая функция (здесь: тело деструктора) — то это и есть unspecified behaviour.
UGN>И что еще считать побочным эффектом?
Например, вывод в консоль.
Ничего локально-катастрофичного в таких побочных эффектах нет, но если от них зависит логика программы, то она может здорово пострадать.
Здравствуйте, Кодт, Вы писали:
К>Отдельного пункта нет. Однако же, если ты не можешь, исходя из синтаксиса, утверждать — сколько раз и в каком порядке будет выполнена некая функция (здесь: тело деструктора) — то это и есть unspecified behaviour.
UGN>>И что еще считать побочным эффектом?
К>Например, вывод в консоль.
К>Ничего локально-катастрофичного в таких побочных эффектах нет, но если от них зависит логика программы, то она может здорово пострадать.
Не согласен... Сколько раз будет вызван тот или иной конструктор — это действительно предугадать сложно. Но сколько раз будет вызван деструктор можно сказать точно — столько же, сколько и все конструкторы данного класса. По-моему этого вполне достаточно. Я не представляю как в данном случае побочное поведение, например, вывод в консоль, может разрушить логику программы?
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
Здравствуйте, Кодт, Вы писали:
UGN>>И что еще считать побочным эффектом?
К>Например, вывод в консоль.
Ну, про консоль ты уже упоминал.
Вопрос в другом.
Каково определение побочных эффектов в С++?
К>Ничего локально-катастрофичного в таких побочных эффектах нет, но если от них зависит логика программы, то она может здорово пострадать.
Здравствуйте, Кодт, Вы писали:
UGN>>Это вывод из отдельных положений стандарта или там есть отдельный пункт с таким утверждением?
К>Отдельного пункта нет. Однако же, если ты не можешь, исходя из синтаксиса, утверждать — сколько раз и в каком порядке будет выполнена некая функция (здесь: тело деструктора) — то это и есть unspecified behaviour.
RVO/NRVO
... << RSDN@Home 1.1.3 beta 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, UGN, Вы писали:
UGN>Каково определение побочных эффектов в С++?
Вроде это: 1.9/7
Accessing an object designated by a volatile lvalue (basic.lval), modifying an object, calling a library I/O function, or calling a function that does any of those operations are all side effects, which are changes in the state of the execution environment. ...
> L_L>Так плевать на интел. У VC то как? Смотри, кстати, 8.5.3 / 5 , стр. 148, то место, где 93) > > Я собственно не веню компилятор в том что он вызывает 2 раза деструктор, а не один, проблема то в другом. Почему от того, есть ли конструктор или нет, зависит его поведение, и потом так сильно. Малоли что я могу делать в своей программе в этом деструкторе, а потом добавлю конструктор и ее поведение поменяется коренным образом. Как то это не правельно.
Естественно, неправильно. Т.е. неправильно, то что поведение твоей программы так радикально меняется от лишнего копирования. Стандарт явно разрешает компилятору как вводить неявные копии объектов (см. ссылки выше), так и оптимизировать "лишние" вызовы конструкторов копирования вне зависимости от наличия побочных эффектов в конструкторе копирования и деструкторе:
12.8/15 When certain criteria are met, an implementation is allowed to omit the copy construction of a class object, even if the copy constructor and/or destructor for the object have side effects.
Posted via RSDN NNTP Server 1.9 alpha
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен