placement new (this) в конструкторе
От: σ  
Дата: 29.03.18 07:49
Оценка: 9 (2)
Вопрос ИСКЛЮЧИТЕЛЬНО юридический, с точки зрения стандарта языка.
Мнения про недопустимость такого стиля и предложения заменить на delegating constructors не интересуют.

Так вот. Мне встречалось утверждение что вызов другого конструктора изнутри данного:
Klass::Klass(some_params)
{
    new (this) Klass(other_params);
}

приводит к UB.

Это так или нет? И почему?
Re: placement new (this) в конструкторе
От: GhostCoders Россия  
Дата: 29.03.18 07:53
Оценка: -1
Здравствуйте, σ, Вы писали:

σ>Вопрос ИСКЛЮЧИТЕЛЬНО юридический, с точки зрения стандарта языка.

σ>Это так или нет? И почему?
Не знаю что там в стандарте, но по логике вещей такая конструкция допустима, и, думаю, вполне может себе использоваться
в С++ до 11 стандарта.
Третий Рим должен пасть!
Re[2]: placement new (this) в конструкторе
От: PowerUserX  
Дата: 29.03.18 08:16
Оценка:
Здравствуйте, GhostCoders, Вы писали:

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


σ>>Вопрос ИСКЛЮЧИТЕЛЬНО юридический, с точки зрения стандарта языка.

σ>>Это так или нет? И почему?
GC> Не знаю что там в стандарте, но по логике вещей такая конструкция допустима, и, думаю, вполне может себе использоваться
GC>в С++ до 11 стандарта.


Здравствуйте!

Тоже с точки кодонаписания — тоже проблем не вижу.
Но, конструктор — генерит asm для VTBL + конструкторы для полей
Т.е. у тебя

Klass::Klass(some_params)
{
// Тута компилер сгенерит код

new (this) Klass(other_params); // И тута компилер сгенерит код
}

Хотя они (компилеры) умные сейчас — мот и не будет...
Re: placement new (this) в конструкторе
От: K13 http://akvis.com
Дата: 29.03.18 09:14
Оценка: 11 (3)
σ>приводит к UB.
σ>Это так или нет? И почему?

Достаточно одному из членов класса или предку захватывать какой-либо ресурс в конструкторе -- и получим повторный захват (утечку / дидлок) в placement new без освобождения уже захваченного.
Re[2]: placement new (this) в конструкторе
От: uzhas Ниоткуда  
Дата: 29.03.18 09:43
Оценка: +1 :)
Здравствуйте, K13, Вы писали:

K13>дидлок


запишу в блокнотик
Re[3]: placement new (this) в конструкторе
От: CyberDemon Россия  
Дата: 29.03.18 10:30
Оценка:
Здравствуйте, uzhas, Вы писали:

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


K13>>дидлок


U>запишу в блокнотик

Главное, Д и Л не перепутать
Re[3]: placement new (this) в конструкторе
От: Дрободан Фрилич СССР  
Дата: 29.03.18 12:22
Оценка:
uzhas:

K13>>дидлок

U>запишу в блокнотик
Главное, чтобы стёк не переполнился.
Модератор-националист Kerk преследует оппонентов по политическим мотивам.
Re: placement new (this) в конструкторе
От: N. I.  
Дата: 29.03.18 14:00
Оценка: 18 (3) :)))
σ:

σ>Вопрос ИСКЛЮЧИТЕЛЬНО юридический


Статья 273 УК

σ>Мне встречалось утверждение что вызов другого конструктора изнутри данного:

σ>
σ>Klass::Klass(some_params)
σ>{
σ>    new (this) Klass(other_params);
σ>}
σ>

σ>приводит к UB.

σ>Это так или нет? И почему?


Похоже на неявное undefined behavior — это когда в стандарте попросту нет описания того, как некая конструкция должна работать. Насколько я вижу, формально объект, создаваемый конструктором Klass(some_params), и объект, создаваемый выражением new (this) Klass(other_params), — это два разных объекта, и какой там винегрет получится при попытке перезаписать чем-то левым память первого объекта в процессе его создания, непонятно. Закончить время жизни первого объекта создание второго не может, т.к. время жизни первого ещё не началось (из тела конструктора ещё не вышли). В общем, что мы имеем:

1. Допустимость делать reuse памяти для объекта under construction и/или последствия такого действия, вроде, нигде не прописаны.

2. В каком состоянии будет пребывать программа в момент, когда должно стартануть время жизни первого объекта (чью память мы вероломно перезаписали каким-то другим объектом, который не подпадает под специальный случай для subobjects), тоже нигде не прописано.

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

Тут, пожалуй, можно подумать над тем, когда именно ожидать возникновение undefined behavior: в момент входа управления в конструктор второго объекта, в момент выхода управления из конструктора первого объекта или же в момент первой попытки сделать с их сочетанием что-нибудь такое, что требует наличие валидного объекта. Пожалуй, я бы поставил на первый вариант — возникновение undefined behavior прямо на входе управления в конструктор второго объекта (из соображений п.1 выше).
Re: placement new (this) в конструкторе
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 29.03.18 15:08
Оценка:
Здравствуйте, σ, Вы писали:

σ>приводит к UB.

Конкретно этот пример привёдт только к проблемама уровня RAII (особенно если там иерархия), но про это сказали.
σ>Это так или нет?
Если понимать как работает, то нет. Я реализовывал даже стейт машину используя этот подход, правда в производных классах нельзя при этом добавлять новые данные или виртуальные методы чтобы не сломать память.
Sic luceat lux!
Re: placement new (this) в конструкторе
От: rg45 СССР  
Дата: 29.03.18 15:27
Оценка: 4 (1)
Здравствуйте, σ, Вы писали:

σ>Так вот. Мне встречалось утверждение что вызов другого конструктора изнутри данного:

σ>
σ>Klass::Klass(some_params)
σ>{
σ>    new (this) Klass(other_params);
σ>}
σ>

σ>приводит к UB.
σ>Это так или нет? И почему?

В принципе, N.I. все объяснил, но я хочу слегка дополнить. Если бы речь шла не о конструкторе, а об обычной нестатической функции-члене, при условии, что класс Klass имеет тривиальный деструктор, такой прием был бы легален. В 6.8/6 (Object lifetime) есть даже в примере нечто похожее:

struct B {
  virtual void f();
  void mutate();
  virtual ~B();
};
struct D1 : B { void f(); };
struct D2 : B { void f(); };
void B::mutate() {
  new (this) D2; // reuses storage — ends the lifetime of *this
  f();           // undefined behavior
  ... = this;    // OK, this points to valid memory
}


Когда же нечто подобное происходит в конструкторе, это совсем другое дело — формально, время жизни объекта начинается только после окончания конструирования. И о том, как должна повести себя программа в стандарте ничего не сказано.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re: placement new (this) в конструкторе
От: alexanderfedin США http://alexander-fedin.pixels.com/
Дата: 29.03.18 17:46
Оценка: +1
Здравствуйте, σ, Вы писали:

σ>Вопрос ИСКЛЮЧИТЕЛЬНО юридический, с точки зрения стандарта языка.

σ>Мнения про недопустимость такого стиля и предложения заменить на delegating constructors не интересуют.

σ>Так вот. Мне встречалось утверждение что вызов другого конструктора изнутри данного:

σ>
σ>Klass::Klass(some_params)
σ>{
σ>    new (this) Klass(other_params);
σ>}
σ>

σ>приводит к UB.

σ>Это так или нет? И почему?

Я бы посоветовал, чтобы не ломалось, сделать вот так:
Klass::Klass(some_params) : Klass(other_params)
{
    ...
}

Тебе же просто хочется зареюзать конструктор, так?
Respectfully,
Alexander Fedin.
Re[2]: placement new (this) в конструкторе
От: σ  
Дата: 30.03.18 16:32
Оценка:
N. I.:

NI>σ:


σ>>Вопрос ИСКЛЮЧИТЕЛЬНО юридический


NI>Статья 273 УК


σ>>Мне встречалось утверждение что вызов другого конструктора изнутри данного:

σ>>
σ>>Klass::Klass(some_params)
σ>>{
σ>>    new (this) Klass(other_params);
σ>>}
σ>>

σ>>приводит к UB.

σ>>Это так или нет? И почему?


NI>Похоже на неявное undefined behavior — это когда в стандарте попросту нет описания того, как некая конструкция должна работать.


Я хотел поспорить и сказать, что поведение определено в http://eel.is/c++draft/basic.life#6 и this можно использовать как указатель на сторадж, но понял, что, оказывается, я проглядел "For an object under construction or destruction, see [class.cdtor]". Т.е. объект может быть не только в двух состояниях: когда лайфтайм ещё не начался (уже закончился) или уже начался (и ещё не закончился), но ещё и в "промежуточном" — under construction/destruction.

В общем, вопроса почему UB больше нет — я просто невнимательно читал параграф стандарта.
Re: placement new (this) в конструкторе
От: MasterZiv СССР  
Дата: 02.04.18 13:31
Оценка: -2
Здравствуйте, σ, Вы писали:

σ>Вопрос ИСКЛЮЧИТЕЛЬНО юридический, с точки зрения стандарта языка.

σ>Мнения про недопустимость такого стиля и предложения заменить на delegating constructors не интересуют.

σ>Так вот. Мне встречалось утверждение что вызов другого конструктора изнутри данного:

σ>
σ>Klass::Klass(some_params)
σ>{
σ>    new (this) Klass(other_params);
σ>}
σ>

σ>приводит к UB.

Это UB.
Для каждого объекта, для которого вызван конструктор, должен быть вызван деструктор.
Для объектов, управляемых через placement new / delete деструкторы должны быть вызваны
руками. тут этого нет. Конструктор Klass уже сработал, а деструктор его не вызывается.
Объект, конструируемый по placement new также должен создаваться на базе памяти, в которой
не существует валидного (т.е. не прошедшего через деструктор) объекта. Тут это тоже не
соблюдается.
Re[2]: placement new (this) в конструкторе
От: σ  
Дата: 02.04.18 16:49
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>Для каждого объекта, для которого вызван конструктор, должен быть вызван деструктор.


Такого правила нет.

Можно переиспользовать память под объектом не вызывая его деструктора http://eel.is/c++draft/basic.life#5:
A program may end the lifetime of any object by reusing the storage which the object occupies or by explicitly calling the destructor for an object of a class type with a non-trivial destructor.
For an object of a class type with a non-trivial destructor, the program is not required to call the destructor explicitly before the storage which the object occupies is reused or released;

(Это, конечно, не позволяет placement new в конструкторе).
Отредактировано 02.04.2018 16:53 σ . Предыдущая версия .
Re: placement new (this) в конструкторе
От: Caracrist https://1pwd.org/
Дата: 07.04.18 19:09
Оценка:
Здравствуйте, σ, Вы писали:

σ>приводит к UB.

σ>почему?

Klass::Klass(some_params)
{
    new (this) Klass(other_params);
}
Klass::Klass(other_param)
{
    throw oops;
}


вопрос: сколько раз разрушится каждый из мемберов?
~~~~~
~lol~~
~~~ Single Password Solution
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.