powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / throw class
19 сообщений из 19, страница 1 из 1
throw class
    #38272952
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Следующий код:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
#include <stdio.h>

class a {
public:
  int f;
  a(int v) { f = v; };
  a(a& o) { f = o.f+1; o.f=0; printf("a copy invoked\n"); };
  ~a() { printf("a destructed\n"); };
};

class b: public a {
public:
  int k;
  b(int v): a(v) { k = v-1; };
  ~b() { printf("b destructed\n"); };
};

int main()
{
  b x(2);
  printf("x.f = %d\nx.k = %d\n", x.f, x.k);
  try
  {
  try
   {
    throw b(3);
   }
   catch (const b& ex)
   {
     printf("ex.f = %d\nex.k = %d\n", ex.f, ex.k);
     throw;
   }
  }
  catch (const b& ex)
  {
    printf("ex2.f = %d\nex2.k = %d\n", ex.f, ex.k);
  }
}


MSVC 10 нормально компилирует, GCC 4.5.1 - отказывается, заявляя
Код: sql
1.
2.
3.
4.
5.
aaa.cpp: In function `int main()':
aaa.cpp:26: error: no matching function for call to `b::b(b)'
aaa.cpp:11: note: candidates are: b::b(b&)
aaa.cpp:14: note:                 b::b(int)
aaa.cpp:26: error:   in thrown expression


К чему бы это?..
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
throw class
    #38272970
В вашем случае GCC видимо не использует оптимизацию и при вызове throw b(3); пытается лишний раз скопировать это значение. Ну а так как конструктора копирования у b нет то и выдает ошибку.

В чем проблема сделать так?
Код: plaintext
1.
2.
3.
4.
5.
try
   {
    b ex(3)
    throw ex;
   }
...
Рейтинг: 0 / 0
throw class
    #38272981
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если копнуть глубже, то проблема спровоцирована тем, что наличие юзерского конструктора базового класса a(a& o) не дает компилятору автоматически сгенерировать конструктор копирования a(const a& o) и как следствие также невозможно сгенерировать конструктор копирования наследника b(const b& o).
Поэтому копирование временного объекта b(3) невозможно (почему компилятор вообще захотел его копировать - отдельный вопрос).
Правильным решением думаю будет объявить явный конструктор копирования a(const a& o).
Тогда b(const b& o) будет сгенерирован автоматически, и можно будет использовать форму throw b(3)
...
Рейтинг: 0 / 0
throw class
    #38273049
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
не использует оптимизациюВ чем проблема сделать так?
Хм, так действительно работает, хоть и копирует объект лишний раз.

Anatoly MoskovskyПоэтому копирование временного объекта b(3) невозможно

А почему компилятор отказывается использовать для копирования конструктор a(a& o)?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
throw class
    #38273096
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovА почему компилятор отказывается использовать для копирования конструктор a(a& o)?
На временные или константные объекты нельзя ссылаться через неконстантные ссылки.
...
Рейтинг: 0 / 0
throw class
    #38273107
Anatoly MoskovskyDimitry SibiryakovА почему компилятор отказывается использовать для копирования конструктор a(a& o)?
На временные или константные объекты нельзя ссылаться через неконстантные ссылки.
Да. Это MSVC отходит от стандарта и позволяет делать не константные ссылки на временные объекты поэтому первый пример и проходит на нём.
...
Рейтинг: 0 / 0
throw class
    #38273115
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyНа временные или константные объекты нельзя ссылаться через
неконстантные ссылки.
Фишка, однако, ещё и в том, что когда я объявляю copy constructor с const, то всё
компилируется и работает, но этот конструктор не вызывается.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
throw class
    #38273121
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovФишка, однако, ещё и в том, что когда я объявляю copy constructor с const, то всё
компилируется и работает, но этот конструктор не вызывается.
Это можно объяснить тем, что по стандарту программа дожна быть написана так, как будто никакой оптимизации нет. Но компилятор имеет право для оптимизации убирать копирование через промежуточные объекты.
Т.е. компилятор не мог откомпилировать потому что не было конструктора копирования, но как только конструктор добавили - компилятор смог соптимизировать лишнее копирование.
...
Рейтинг: 0 / 0
throw class
    #38273122
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyТ.е. компилятор не мог откомпилировать потому что не было
конструктора копирования, но как только конструктор добавили - компилятор смог
соптимизировать лишнее копирование.
Странные люди сидят в комитетах по стандартам...

Ещё вопрос: в таком случае насколько безопасно в конструкторе снимать константность при
помощи const_cast чтобы изменить что-то в исходном объекте?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
throw class
    #38273124
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovСтранные люди сидят в комитетах по стандартам...
А на мой взгляд это очень логичное и удобное правило.
Dimitry SibiryakovЕщё вопрос: в таком случае насколько безопасно в конструкторе снимать константность при
помощи const_cast чтобы изменить что-то в исходном объекте?
Проблема заключается в том что в такой конструктор могут попасть не только временные объекты, но и по настоящему константные (чей владелец не предполагает что они кем-то могут быть изменены).
Так что если вы можете гарантировать отсутствие константных объектов - то вполне безопасно. Иначе - нет.

Если у вас С++11, то полностью безопасное решения этого вопроса (семантика перемещения) реализуется через rvalue-ссылки (&&).

Для компиляторов до С++11 в Бусте есть библиотека Boost.Move которая помогает реализовать семантику перемещения.
Но я ее никогда не использовал и не могу сказать что она умеет и как это выглядит в коде.
...
Рейтинг: 0 / 0
throw class
    #38273142
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyА на мой взгляд это очень логичное и удобное правило.

По поводу константных объектов - согласн, но приравнивать к ним временные...
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
throw class
    #38273190
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovПо поводу константных объектов - согласн, но приравнивать к ним временные...
Их никто не приравнивает.
Вы шо-то неправильно поняли.
...
Рейтинг: 0 / 0
throw class
    #38273209
Фотография NekZ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Эммм... Извиняюсь, конечно... А деструктор разве не надо объявить виртуальным в этом случае?
...
Рейтинг: 0 / 0
throw class
    #38273222
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NekZЭммм... Извиняюсь, конечно... А деструктор разве не надо объявить виртуальным в этом случае?
В этом случае - не обязательно.
...
Рейтинг: 0 / 0
throw class
    #38273224
NekZЭммм... Извиняюсь, конечно... А деструктор разве не надо объявить виртуальным в этом случае?
Зачем? Полиморфизм тут не используется, никто не создает динамически объект класса b, не хранит указатель типа класса a и не удаляет через него.

Хотя он тут и не помешает, но и не поможет ничем.
А советы - в общем случае всегда делать деструктор виртуальным - тоже от балды, особенно когда хранятся массивы из миллионов объектов подобных классов.
...
Рейтинг: 0 / 0
throw class
    #38273228
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyИх никто не приравнивает.
Вы шо-то неправильно поняли.
Возможно. Но что именно:
Anatoly MoskovskyНа временные или константные объекты нельзя ссылаться через
неконстантные ссылки.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
throw class
    #38273230
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov,

А в переменную типа int нельзя записать строку или список.
По вашей логике получается что строки приравнены к спискам.
...
Рейтинг: 0 / 0
throw class
    #38273233
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyПо вашей логике получается что строки приравнены к спискам.

А по вашей логике получается, что тип у временного объекта отличается от "обычного" так же
как целое от строки.
Ну да против объективной реальности всяко не попрёшь... Раз GCC говорит, что отличается,
значит отличается.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
throw class
    #38273295
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovА по вашей логике получается
Не надо про мою логику. Давайте про С++.
Временные и константные объекты в С++ не приравнены.
Из того утвеждения, из которого вы сделали вывод, что они приравнены, это не следует.
Что тут не понятно-то?
...
Рейтинг: 0 / 0
19 сообщений из 19, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / throw class
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]