Время разрушения фактических параметров
От: Went  
Дата: 28.03.10 11:23
Оценка:
Здрасте. Стандартизирована ли точка выполнения программы, когда вызовутся деструкторы объектов, созданных в процессе вызова функции. То есть вот:
struct X
{
  X::~X()
  {
    cout << "Booo!!!";
  }
};

void x(const X&)
{
}

int main()
{
  x(X());

  cout << "Foo!!!";

  return 0;
}

Могу ли я быть уверен, что Boo вызовется раньше, чем Foo!!!? Или каждый компилятор свободен в своем выборе?
Re: Время разрушения фактических параметров
От: remark Россия http://www.1024cores.net/
Дата: 28.03.10 11:30
Оценка: 2 (1) +2
Здравствуйте, Went, Вы писали:

W>Здрасте. Стандартизирована ли точка выполнения программы, когда вызовутся деструкторы объектов, созданных в процессе вызова функции. То есть вот:

W>Могу ли я быть уверен, что Boo вызовется раньше, чем Foo!!!? Или каждый компилятор свободен в своем выборе?

Да, можешь быть уверен. Временные объекты рушатся в конце т.н. full expression (грубо говоря, там, где стоит ";").


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: Время разрушения фактических параметров
От: Went  
Дата: 28.03.10 12:01
Оценка:
Здравствуйте, remark, Вы писали:

R>Да, можешь быть уверен. Временные объекты рушатся в конце т.н. full expression (грубо говоря, там, где стоит ";").


Спасибо. Хорошо, что стандартизировано, хотя, мне кажется, что было бы логичнее разрушать их по сразу выходу из функции, не дожидаясь конца выражения.
Re[3]: Время разрушения фактических параметров
От: remark Россия http://www.1024cores.net/
Дата: 28.03.10 12:09
Оценка:
Здравствуйте, Went, Вы писали:

R>>Да, можешь быть уверен. Временные объекты рушатся в конце т.н. full expression (грубо говоря, там, где стоит ";").


W>Спасибо. Хорошо, что стандартизировано, хотя, мне кажется, что было бы логичнее разрушать их по сразу выходу из функции, не дожидаясь конца выражения.


А смысл? Так ими можно воспользоваться несколько раз:
X const& foo(X const& x)
{
    cout << x.data++;
    return x;
}

int main()
{
    foo(foo(foo(X())));
}


Или даже ещё лучше пример будет:
X const& init(X const&)
{
  const_cast<X&>(x).data = rand();
}

void foo(X const& x1, X const X2);

int main()
{
  foo(init(X()), init(X()));
}


В общем соль в том, что на этот объект могут быть ссылки после вызова функции, даже если он и временный.
Или даже ещё лучше пример:
lock(x), x->foo();

или:
lock(x)->f();

Смотри:
http://rsdn.ru/forum/cpp/2937445.1.aspx
Автор: remark
Дата: 04.05.08



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: Время разрушения фактических параметров
От: _nn_ www.nemerleweb.com
Дата: 28.03.10 12:10
Оценка:
Здравствуйте, Went, Вы писали:

W>Здравствуйте, remark, Вы писали:


R>>Да, можешь быть уверен. Временные объекты рушатся в конце т.н. full expression (грубо говоря, там, где стоит ";").


W>Спасибо. Хорошо, что стандартизировано, хотя, мне кажется, что было бы логичнее разрушать их по сразу выходу из функции, не дожидаясь конца выражения.


Вы можете явно указать ваши действия.
1.
...
f(X()); // ~X()
...


2.
...

X tempX;

f(tempX);

...

// ~X()
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[4]: Время разрушения фактических параметров
От: Went  
Дата: 28.03.10 15:05
Оценка:
Здравствуйте, _nn_, Вы писали:

__>Вы можете явно указать ваши действия.


Просто я знаю толк в извращениях Представьте себе такую шнягу: "постдеструктор", который должен выполнится автоматом тогда, когда вызван самый верхний конструктор. Долго думал, как это сделать, в конце концов сделал такое:
struct PostIniter
{
  ~PostIniter()
  {
    object->postBase();
  }

  Base* object;
};

struct Base
{
  Base(PostIniter& post_initer = PostIniter())
  {
    post_initer.object = this;
  }

  virtual postBase() {/*Это вызывается позже конструктора Derived*/}}
};

struct Derived : Base
{
};

Это фишка работает, но грязно, ибо глючет в случаях вроде:
add_element(new Derived);

Ибо add_element срабатывает раньше postBase. А обидно
Re[5]: Время разрушения фактических параметров
От: remark Россия http://www.1024cores.net/
Дата: 28.03.10 16:14
Оценка: +1
Здравствуйте, Went, Вы писали:

W>Просто я знаю толк в извращениях Представьте себе такую шнягу: "постдеструктор", который должен выполнится автоматом тогда, когда вызван самый верхний конструктор. Долго думал, как это сделать, в конце концов сделал такое:

W>
W>struct PostIniter
W>{
W>  ~PostIniter()
W>  {
W>    object->postBase();
W>  }

W>  Base* object;
W>};

W>struct Base
W>{
W>  Base(PostIniter& post_initer = PostIniter())
W>  {
W>    post_initer.object = this;
W>  }

W>  virtual postBase() {/*Это вызывается позже конструктора Derived*/}}
W>};

W>struct Derived : Base
W>{
W>};
W>

W>Это фишка работает, но грязно, ибо глючет в случаях вроде:
W>
W>add_element(new Derived);
W>

W>Ибо add_element срабатывает раньше postBase. А обидно

Так просто ты тут не отделаешься. Тебе надо добавлять дефолтный параметр PostIniter& post_initer = PostIniter() и во все произвольные классы.

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

Посмотри вот это, может заинтересует:
http://rsdn.ru/forum/cpp/2687901.aspx
Автор: remark
Дата: 10.10.07




1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[6]: Время разрушения фактических параметров
От: uzhas Ниоткуда  
Дата: 28.03.10 16:49
Оценка:
Здравствуйте, remark, Вы писали:

R>Так просто ты тут не отделаешься. Тебе надо добавлять дефолтный параметр PostIniter& post_initer = PostIniter() и во все произвольные классы.


не надо учить плохому
нельзя передавать временные объекты в функцию (и в конструктор) по неконстантной ссылке

вот такой код не компилируется в comeau
struct B
{
};

struct A
{
  A(B& b = B()) // error: initial value of reference to non-const must be an lvalue
  {}
};

void g()
{
  A a;
}


как я понимаю, неконстантые ссылки на временные объекты поддерживает Visual Studio с включенными расширениями
Re[6]: Время разрушения фактических параметров
От: Went  
Дата: 28.03.10 18:05
Оценка: :)
Здравствуйте, remark, Вы писали:

R>Так просто ты тут не отделаешься. Тебе надо добавлять дефолтный параметр PostIniter& post_initer = PostIniter() и во все произвольные классы.


Да, но я тут описал сильно упрощенную модель. В реале это немного сложнее и полезнее. Грубо говоря, PostIniter — это семейство классов с разной стратегией инициализации и разнообразными параметрами.

R>Плюс будет плохо работать при исключениях, ибо работа выполняется в деструкторе.


Да, не учел. Очередная неприятность.

R>Посмотри вот это, может заинтересует:

R>http://rsdn.ru/forum/cpp/2687901.aspx
Автор: remark
Дата: 10.10.07


А чем? Там явно вызывается init/finit, мне нужен именно неявный вызов.
Re[7]: Время разрушения фактических параметров
От: Went  
Дата: 28.03.10 18:06
Оценка:
Здравствуйте, uzhas, Вы писали:

U>не надо учить плохому

U>нельзя передавать временные объекты в функцию (и в конструктор) по неконстантной ссылке

Я написал сильно упрощенный вариант. В реале этой проблемы не возникает. Хотя, да, студия пропускает такие финты на раз, вива анархия
Re[7]: Время разрушения фактических параметров
От: remark Россия http://www.1024cores.net/
Дата: 28.03.10 18:29
Оценка:
Здравствуйте, Went, Вы писали:

R>>Так просто ты тут не отделаешься. Тебе надо добавлять дефолтный параметр PostIniter& post_initer = PostIniter() и во все произвольные классы.


W>Да, но я тут описал сильно упрощенную модель. В реале это немного сложнее и полезнее. Грубо говоря, PostIniter — это семейство классов с разной стратегией инициализации и разнообразными параметрами.


Раз в каждый производный класс всё равно добавлять код, можно попробовать явно определять MDT и из него явно вызывать пост-инициализацию. По-краней мере будет стабильно работать с исключениями (и если исключение вылетает во время выполнения конструктора, и если исключение вылетает во время работы пост-инициализации), и в случае, когда объект начинает использоваться до конца full expression.


R>>Плюс будет плохо работать при исключениях, ибо работа выполняется в деструкторе.


W>Да, не учел. Очередная неприятность.


Тут могу только предложить в конструкторе PostIniter ассёртом проверять, что std::uncaught_exception()== false. В деструкторе если std::uncaught_exception()== false, то вызывать пост-инициализацию, в противном случае не вызывать. Тут вроде как получается, что из пост-инициализации можно кидать исключения, не смотря на то, что она делается в деструкторе (хммм... я ничего не упускаю?).
Это несколько сужает область применения, но с практической т.з. вроде незначительно.
Хотя и тут могут быть проблемы, если исключение произошло не в конструкторе, а между завершением конструктора и концом full expression — можем получить объект без пост-инициализации. Что-то типа:
remember(new Derived()), potentially_throws();

Не, всё-таки без явного вызова тут ничего хорошего не получается...



R>>Посмотри вот это, может заинтересует:

R>>http://rsdn.ru/forum/cpp/2687901.aspx
Автор: remark
Дата: 10.10.07


W>А чем? Там явно вызывается init/finit, мне нужен именно неявный вызов.


А там реализуется семантика конструкторов/деструкторов для произвольных функций. Т.е. автоматически вызывается функция из каждого класса в иерархии в порядке от базового к производному или обратно.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[7]: Ну вы блин, даёте!
От: Erop Россия  
Дата: 29.03.10 05:47
Оценка:
Здравствуйте, Went, Вы писали:

W>Да, но я тут описал сильно упрощенную модель. В реале это немного сложнее и полезнее. Грубо говоря, PostIniter — это семейство классов с разной стратегией инициализации и разнообразными параметрами.


Ужос!!! Интересно бы понять, что за выгоды и вкусности такие предоставляет подход, что ты готов мириться с read-only кодом?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Время разрушения фактических параметров
От: Erop Россия  
Дата: 29.03.10 05:54
Оценка:
Здравствуйте, Went, Вы писали:

W>Ибо add_element срабатывает раньше postBase. А обидно


А чем не устраивают стандартные подходы к проблеме?
Там фабрики всякие, pimpl и д.р?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[7]: Время разрушения фактических параметров
От: Erop Россия  
Дата: 29.03.10 06:06
Оценка:
Здравствуйте, uzhas, Вы писали:

U>нельзя передавать временные объекты в функцию (и в конструктор) по неконстантной ссылке


Зато у временных объектов можно позвать неконтантный метод...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Время разрушения фактических параметров
От: remark Россия http://www.1024cores.net/
Дата: 29.03.10 15:34
Оценка: 2 (1)
Здравствуйте, Went, Вы писали:

W>Просто я знаю толк в извращениях Представьте себе такую шнягу: "постдеструктор", который должен выполнится автоматом тогда, когда вызван самый верхний конструктор. Долго думал, как это сделать, в конце концов сделал такое:


W>Это фишка работает, но грязно, ибо глючет в случаях вроде:

W>
W>add_element(new Derived);
W>

W>Ибо add_element срабатывает раньше postBase. А обидно

Изложил свои мысли по этому поводу здесь:
http://www.rsdn.ru/forum/cpp/3753973.1.aspx
Автор: remark
Дата: 29.03.10



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[6]: Время разрушения фактических параметров
От: Went  
Дата: 30.03.10 09:56
Оценка:
Здравствуйте, remark, Вы писали:

R>Изложил свои мысли по этому поводу здесь:

R>http://www.rsdn.ru/forum/cpp/3753973.1.aspx
Автор: remark
Дата: 29.03.10


Пасиба, интересно.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.