powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Константный экземпляр класса. Кто как делает?
94 сообщений из 94, показаны все 4 страниц
Константный экземпляр класса. Кто как делает?
    #39647628
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Допустим, есть некий класс и в зависимости от того, является ли экземпляр const или non-const у этого экземпляра либо нет реализации деструктора, либо она есть. Кто как решает подобную задачу?
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39647636
egorych
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devКто как решает подобную задачу?это какая то странная задача))
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39647655
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
egorych, есть необходимость изменить поведение экземпляра класса, когда он const, но если обычные методы можно сделать const и они будут вызываться только для const указателя/ссылки на объект, то конструкторы и деструкторы сделать const, разделив таким образом поведение при создании/разрушении, нельзя.

Вот я и спрашиваю - кто и как решал подобную задачу?
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39647682
blonduser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devegorych, есть необходимость изменить поведение экземпляра класса, когда он const, но если обычные методы можно сделать const и они будут вызываться только для const указателя/ссылки на объект, то конструкторы и деструкторы сделать const, разделив таким образом поведение при создании/разрушении, нельзя.

Вот я и спрашиваю - кто и как решал подобную задачу?

Это где такому учат?
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39647705
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devДопустим, есть некий класс и в зависимости от того, является ли экземпляр const или non-const у этого экземпляра либо нет реализации деструктора, либо она есть. Кто как решает подобную задачу?
Вернись в постановке реальной задачи, а не к черезжопному представлению, как ее делать.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39647710
Фотография NekZ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devegorych, есть необходимость изменить поведение экземпляра класса, когда он const, но если обычные методы можно сделать const и они будут вызываться только для const указателя/ссылки на объект, то конструкторы и деструкторы сделать const, разделив таким образом поведение при создании/разрушении, нельзя.

Вот я и спрашиваю - кто и как решал подобную задачу?
Ну как вариант, можно чекать внутри объекта если хотя бы раз у него вызывался неконстантный мембер, то он неконстантный и уже в деструкторе принимать решение на основе этого флага. Но это дурно пахнет, если честно.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39647725
egorych
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devконструкторы и деструкторы сделать const, разделив таким образом поведение при создании/разрушении, нельзяи это правильно, ибо класс с константным конструктором не получится создать, а с константным деструктором - разрушить )))

PS смотри в stl, там сделали отдельные классы для таких извращённых случаев, iterator и const_iterator как пример
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39647828
Фотография CEMb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если я всё правильно понял, конструкторы вызываются для константных и не константных объектов. Разница только в точке вызова.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39647897
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
egorychи это правильно, ибо класс с константным конструктором не получится создать, а с константным деструктором - разрушить )))

PS смотри в stl, там сделали отдельные классы для таких извращённых случаев, iterator и const_iterator как примерВ том-то и дело, что при инициализации константного объекта он может быть проинициализирован константными значениями без их копирования в кучу, т.е. ссылаться на них, а при разрушении, естественно, не должен пытаться очистить эти ресурсы. Совершенно не хочется проверять в деструкторе, где именно находится ресурс - в куче или в ресурсах бинарного модуля. По всей видимости, придётся как-то выкручиваться через спецификацию шаблона.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39647899
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CEMbЕсли я всё правильно понял, конструкторы вызываются для константных и не константных объектов. Разница только в точке вызова.И точка вызова у них может быть одна и та же. Разница лишь в том, что при вызове константного метода ему прилетает константный this со всеми вытекающими.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39647950
blonduser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devИ точка вызова у них может быть одна и та же. Разница лишь в том, что при вызове константного метода ему прилетает константный this со всеми вытекающими.

При вызове ему прилетает указатель и никто не знает какой он.

https://msdn.microsoft.com/ru-ru/library/07x6b05d.aspx]Ключевое слово const указывает, что значение переменной является постоянным и сообщает компилятору , что программист не должен его изменять.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39647984
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
blonduser, что мешает проверить?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
class A {
  volatile int a;
public :
    void set(int src) const
    {
      int * p_a = reinterpret_cast<int*>(reinterpret_cast<void*>(this)++);
      //int * p_a = reinterpret_cast<int*>((size_t)this + sizeof(void*));
      *p_a = src;
    }
};

Результат компиляции:
Код: plaintext
1.
2.
main.cpp: In member function 'void A::set(int) const':
main.cpp:38:70: error: reinterpret_cast from type 'const A*' to type 'void*' casts away qualifiers
       int * p_a = reinterpret_cast<int*>(reinterpret_cast<void*>(this)++);
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39648003
blonduser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_dev,

С функциями Set const не используется обычно. Но вы знаете толк в извращения!
Это происходит только в момент компиляции.

Мой вариант работает.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
class A {
  volatile int a;
public :
    void set(int src) const
    {
	  int * pA = (int*)(void*)&a;
	  *pA = src;

      //int * p_a = reinterpret_cast<int*>(reinterpret_cast<void*>(this)++);
      //int * p_a = reinterpret_cast<int*>((size_t)this + sizeof(void*));
      //*p_a = src;
    }
};
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39648012
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
blonduserЭто происходит только в момент компиляции.Естественно! Где же еще? :)
Скомпилированный бинарный модуль не хранит информацию о спецификаторах. Ты же понимаешь, что доступ к любому члену экземпляра класса осуществляется по неявному указателю this, который можно указывать, а можно и не указывать в реализации метода, а доступ по константному указателю, это доступ read-only.

P.S. Кстати, попробуй в моём примере строку с ошибкой заменить на строку из комментария. ;)
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39648020
blonduser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_dev,

Так ты что хочешь получить в результате?
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39648076
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
blonduserrdb_dev, так ты что хочешь получить в результате?Об этом я уже всё написал выше, а сейчас мы ушли в небольшой оффтоп на обсуждение особенностей константных методов. Если удастся сделать красивую реализацию на спецификации шаблона с дедукцией, выложу.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39648109
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devДопустим, есть некий класс и в зависимости от того, является ли экземпляр const или non-const у этого экземпляра либо нет реализации деструктора, либо она есть. Кто как решает подобную задачу?

Ты неправ, деструктор у класса есть всегда, и он всегда вызывается.
Реализация при этом одна и та же.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39648112
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devegorych, есть необходимость изменить поведение экземпляра класса, когда он const, но если обычные методы можно сделать const и они будут вызываться только для const указателя/ссылки на объект, то конструкторы и деструкторы сделать const, разделив таким образом поведение при создании/разрушении, нельзя.

Вот я и спрашиваю - кто и как решал подобную задачу?

Ты можешь объявить два конструктора для const и не const объектов, и вызывать их соответственно.
Отличать конструкторы друг от друга придётся руками (можно сделать два наследника, чтобы это было видно в названии класса).
При этом ты можешь в конструкторе инициализировать некий флаг внутри класса, чтобы отличать, является ли данный экземлпяр
const или не является.

Ещё раз, при этом дифференцировать объекты по const|не const тебе придётся руками. Для упрощения можно ещё запрятать
создание экземпляров в фабрику.

P.S. да, задача идиотская, я согласен со всеми, кто так высказывался. Всё против объектной модели С++.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39648191
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivrdb_devДопустим, есть некий класс и в зависимости от того, является ли экземпляр const или non-const у этого экземпляра либо нет реализации деструктора, либо она есть. Кто как решает подобную задачу?

Ты неправ, деструктор у класса есть всегда, и он всегда вызывается.
Реализация при этом одна и та же.Я знаю, что деструктор есть всегда, поэтому и написал не "нет деструктора", а "нет реализации деструктора", имея в виду ~T() {}
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39648201
blonduser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZiv, Не отвлекайте его. Очень хочется на результат посмотреть.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39648218
Leonid Kudryavtsev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZiv...
Отличать конструкторы друг от друга придётся руками (можно сделать два наследника, чтобы это было видно в названии класса).
...
Для упрощения можно ещё запрятать создание экземпляров в фабрику.

В этом случае, проблемы нет вообще.
базовый класс, два наследника: TMyClassInHeap, TMyClassAsRef
и просто virtual деструктор
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39648356
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
blonduser, не дождешься!
С дедукцией не получается, а без неё выходит банальный exactly specialized template, который даже школьник напишет.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39648366
Фотография CEMb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devРазница лишь в том, что при вызове константного метода ему прилетает константный this со всеми вытекающими.Это разница - для компилятора . Код не различает const. Я думаю, компилятор при генерации отличает ctor/dtor-ы от остальных методов. Т.е. ты не сможешь сам его позвать явно (не скомпилируется).
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39648431
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CEMbЭто разница - для компилятора . Код не различает const. Я думаю, компилятор при генерации отличает ctor/dtor-ы от остальных методов. Т.е. ты не сможешь сам его позвать явно (не скомпилируется).Я так и написал: 21428334
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39648487
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivТы можешь объявить два конструктора для const и не const объектов, и вызывать их соответственно.
Отличать конструкторы друг от друга придётся руками (можно сделать два наследника, чтобы это было видно в названии класса).
При этом ты можешь в конструкторе инициализировать некий флаг внутри класса, чтобы отличать, является ли данный экземлпяр
const или не является.

Ещё раз, при этом дифференцировать объекты по const|не const тебе придётся руками. Для упрощения можно ещё запрятать
создание экземпляров в фабрику.

P.S. да, задача идиотская, я согласен со всеми, кто так высказывался. Всё против объектной модели С++.Неа, объявить const конструктор не могу! Конструкторы и деструкторы не могут иметь cv квалификаторы.
В итоге получается два точно специализированных шаблона класса-обёртки (для const и не const) к интересующему классу, плюс typedef'ы для них. Вот так - банально и скучно. Нет возможности специализировать шаблон по объявлению lvalue.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
template<class T> class A_;

template<>
class A_<A const> : public A
{
...
};

template<>
class A_<A> : public A
{
...
};

typedef A_<const A> ClassConstA;
typedef A_<A> ClassA;


Вообще, в C++ очень много "недосказанности". К примеру:
* Есть возможность "сказать" new const Type(), но нет возможности этот const хоть как-то "услышать" в реализации перегруженного оператора new, конструктора или деструктора класса;
* Есть возможность переопределить placement new, но компилятор не симулирует его вызов при определении экземпляра объекта на стеке, хотя, такое поведение было бы логичным;
* Можем специализировать шаблоны с дедукцией по параметрам конструктора, но не можем специализировать шаблоны с дедукцией по типу и квалификаторам объявления lvalue;
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39648590
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZiv, сделал попроще:
Код: plaintext
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.
template <class T = std::nullptr_t> class B;

template <>
class B<std::nullptr_t> : public A
{
  public:

    B()
    {
      printf("B::B()\r\n");
    }

    virtual ~B()
    {
        printf("B::~B()\r\n");
    }
};

template <>
class B<const> : public A
{
  public:

    B()
    {
      printf("const B::B()\r\n");
    }

    virtual ~B()
    {
        printf("const B::~B()\r\n");
    }
};

Объявление:
Код: plaintext
1.
2.
C<> c1;
C<const> c2;


Жаль в C++ нет зарезервированного слова, позволяющего в default подставить <cv-qualifiers type> из объявления lvalue;

Модератор: Будете тут какашками кидаться, выпилю обоих из форума. Не только к тебе относится.
Асанизация проведена.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39648689
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devВообще, в C++ очень много "недосказанности". К примеру:
* Есть возможность "сказать" new const Type(), но нет возможности этот const хоть как-то "услышать" в реализации перегруженного оператора new, конструктора или деструктора класса;
* Есть возможность переопределить placement new, но компилятор не симулирует его вызов при определении экземпляра объекта на стеке, хотя, такое поведение было бы логичным;
* Можем специализировать шаблоны с дедукцией по параметрам конструктора, но не можем специализировать шаблоны с дедукцией по типу и квалификаторам объявления lvalue;

Просто у тебя в голове какой-то другой свой язык, и ты почему-то его называешь "С++"...
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39648692
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devblonduser, не дождешься!
С дедукцией не получается, а без неё выходит банальный exactly specialized template, который даже школьник напишет.

Ну ты всё же сильно переоцениваешь школьников.
В массе они даже не знают, что такое специализация.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39648830
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivrdb_devВообще, в C++ очень много "недосказанности". К примеру:
* Есть возможность "сказать" new const Type(), но нет возможности этот const хоть как-то "услышать" в реализации перегруженного оператора new, конструктора или деструктора класса;
* Есть возможность переопределить placement new, но компилятор не симулирует его вызов при определении экземпляра объекта на стеке, хотя, такое поведение было бы логичным;
* Можем специализировать шаблоны с дедукцией по параметрам конструктора, но не можем специализировать шаблоны с дедукцией по типу и квалификаторам объявления lvalue;

Просто у тебя в голове какой-то другой свой язык, и ты почему-то его называешь "С++"...Ты имеешь в виду только последнее замечание или все три?
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39648939
blonduser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мне было очень интересно увидеть, как и когда ты будешь освобождать те объекты, которые не удалил в деструкторе когда класс был объявлен как "const"?
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39649082
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
blonduserМне было очень интересно увидеть, как и когда ты будешь освобождать те объекты, которые не удалил в деструкторе когда класс был объявлен как "const"?Зачем освобождать то, что не выделяется?
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39649307
blonduser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devЗачем освобождать то, что не выделяется?

Это следовало из твоего первого поста и из 21431824 .

Обычно делают конструктор с параметрами и уже в зависимости от них либо создают мембер-объект, либо указателю присваивают NULL .
В деструкторе очищают те объекты указатель которых не NULL и нет необходимости создавать дополнительные ключи и придумывать шаблоны.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39649319
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
blonduserВ деструкторе очищают те объекты указатель которых не NULL и нет необходимости создавать дополнительные ключи и придумывать шаблоны.Хорошо, поясню на пальцах:
допустим, в конструктор передаётся указатель на константную строку из статических ресурсов бинарного модуля и если объект неконстантный, эту строку надо скопировать в кучу и проинициализировать член-указатель на скопированную строку, а если константный, то можно просто проинициализировать указатель на эту константную строку без её копирования. Соответственно, при разрушении неконстантного объекта тебе надо освободить память из под строки, а при разрушении константного объекта этого делать не надо. Так понятнее?
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39649335
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devblonduserВ деструкторе очищают те объекты указатель которых не NULL и нет необходимости создавать дополнительные ключи и придумывать шаблоны.Хорошо, поясню на пальцах:
допустим, в конструктор передаётся указатель на константную строку из статических ресурсов бинарного модуля и если объект неконстантный, эту строку надо скопировать в кучу и проинициализировать член-указатель на скопированную строку, а если константный, то можно просто проинициализировать указатель на эту константную строку без её копирования. Соответственно, при разрушении неконстантного объекта тебе надо освободить память из под строки, а при разрушении константного объекта этого делать не надо. Так понятнее?
Код: plaintext
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.
// Example program
#include <iostream>
#include <string>
#include <cstring>

class const_C {
    const char *const_string;
    char *nonconst_string;
public:
    const_C(const char* s) {const_string = s; nonconst_string = NULL;}
    const_C(char* s) {const_string = NULL; nonconst_string = strdup(s);}
    void print_state() { if(const_string) std::cout << "i'm a const inited\n"; else if (nonconst_string) std::cout << "i must free a string\n";}
};


const char cstr[] = "hello const";

int main()
{
    char* str = "non const";
    const_C c_obj(cstr);
    const_C obj(str);
    c_obj.print_state();
    obj.print_state();
}


http://cpp.sh/5aj3m

Конструктор понятно как дописать ?
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39649343
egorych
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devХорошо, поясню на пальцах:
допустим, в конструктор передаётся указатель на константную строку из статических ресурсов бинарного модуля и если объект неконстантный, эту строку надо скопировать в кучу и проинициализировать член-указатель на скопированную строку, а если константный, то можно просто проинициализировать указатель на эту константную строку без её копирования. Соответственно, при разрушении неконстантного объекта тебе надо освободить память из под строки, а при разрушении константного объекта этого делать не надо. Так понятнее?великолепная мина, с отличным, отложенным запалом )) здесь прекрасно всё)))
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39649364
blonduser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devдопустим, в конструктор передаётся указатель на константную строку из статических ресурсов бинарного модуля и если объект неконстантный, эту строку надо скопировать в кучу и проинициализировать член-указатель на скопированную строку, а если константный, то можно просто проинициализировать указатель на эту константную строку без её копирования. Соответственно, при разрушении неконстантного объекта тебе надо освободить память из под строки, а при разрушении константного объекта этого делать не надо.

Но ты понимаешь, что указатель можно сделать не константным внутри вызова и изменить строку как угодно?

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

Вот такой механизм тебе не подойдет?
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39649395
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
blonduserНо ты понимаешь, что указатель можно сделать не константным внутри вызова и изменить строку как угодно?Если член-указатель private, то это реализация только моя. Например:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
struct CTest
{
private:
  char* pStr;

public:
  CTest(const char*);
  CTest& operator = (CTest&&);
  CTest& operator += (CTest&&);
};



blonduserИменно для строки я видел шаблон в котором реализован механизм который ты описал.
Но там передаются объекты строки, а указатель на строку один.
Если в какой-то момент времени строку надо изменить, то создается копия строки.
При удалении последнего объекта очищается и строка.Я уже думал над этим, но так как у меня в структуре не может хранится ничего, кроме одного лишь указателя, придётся сделать static переменную внутри какого-нибудь protected метода, указывающую на экземпляр std::map, который будет дополняться из конструктора (подчищаться из деструктора) и хранить указатели на экземпляры структуры с флагами инициализации, а сам метод будет возвращать состояние инициализации.

Но при любой реализации есть одна загвоздка - при вызове CTest("The test message"), короткая строка может быть передана целиком в кадре стека вместе с указателем на неё и, естественно, может быть затёрта кадрами других вызовов после выхода из области видимости. Или же, может быть передан указатель на строку из кучи, а потом память из под этой строки будет освобождена.
В итоге получается, что при использовании не очень больших строк, накладные расходы на отлов всех этих нюансов перекрывают выгоды от некопирования строки.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39649397
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
egorychвеликолепная мина, с отличным, отложенным запалом )) здесь прекрасно всё)))А то!
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39649400
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Siemargl, указатель внутри структуры, принципиально, только один.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39649423
blonduser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devЯ уже думал над этим, но так как у меня в структуре не может хранится ничего, кроме одного лишь указателя

Ну так одного указателя достаточно.
Ему можно присвоить всё что угодно главное не забывать что присвоил.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39649521
Фотография ну я
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если разнести собсно конструктор и инициализацию, то в принципе можно.
Код: plaintext
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.
class C
{
	char* data;
public:
	C()
	{
		// empty constructor, nothing to do in destructor
		data = NULL;
	};
	void init(const char* src)
	{
		// non-const constructor replacer
		printf("non-const %s\n", src);
	};
	void init(const char* src) const
	{
		// const constructor replacer
		printf("const %s\n", src);
	};
	~C()
	{
		if(data)
		{
			// destroy owned data
		}
	};
};
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39649541
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devSiemargl, указатель внутри структуры, принципиально, только один.Тогда придется хранить флаг константности инициализации.

Но вообще то проще делать копию в любом случае, если только данных не заоблачное кол-во.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39649562
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Еще можно использовать constexpr и вынести время жизни объекта вообще на стадию компиляции.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39649753
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devMasterZivпропущено...


Просто у тебя в голове какой-то другой свой язык, и ты почему-то его называешь "С++"...Ты имеешь в виду только последнее замечание или все три?

Все три.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39649775
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devblonduserВ деструкторе очищают те объекты указатель которых не NULL и нет необходимости создавать дополнительные ключи и придумывать шаблоны.Хорошо, поясню на пальцах:
допустим, в конструктор передаётся указатель на константную строку из статических ресурсов бинарного модуля и если объект неконстантный, эту строку надо скопировать в кучу и проинициализировать член-указатель на скопированную строку, а если константный, то можно просто проинициализировать указатель на эту константную строку без её копирования. Соответственно, при разрушении неконстантного объекта тебе надо освободить память из под строки, а при разрушении константного объекта этого делать не надо. Так понятнее?

Твои представления об объектной модели С++ несколько проще, чем она есть на самом деле.
Помимо константных и неконстантных объектов есть ещё объекты временные, и семантика перемещения, которая работает и с константными, и с неконстантными, и с временными объектами.

Тебе надо ОТДЕЛЬНО, ОРТОГОНАЛЬНО К КОНСТАНТНОСТИ ОБЪЕКТА реализовать эту фичу:
твой объект должен хранить либо ссылку на константу либо реальное значение, и знать, на что он ссылается в данный момент.

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

если эта строка меняется внутри данного объекта, то менять её на ссылку на константные ресурсы либо на реальное значение.

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

И сделать это, кажется, достаточно просто, нужно хранить внутри

std::variant< std::string, std::string_view >

Я не знаю всю твою семантику, но похоже, что тебе это подойдёт, при этом не нужно делать почти вообще ничего.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39649794
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivВсе три.Давай по пунктам?

* Есть возможность "сказать" new const Type(), но нет возможности этот const хоть как-то "услышать" в реализации перегруженного оператора new, конструктора или деструктора класса;

Зачем возможность писать const, если при создании экземпляра класса в куче этот const, ровным счётом, ни на что не влияет?

* Есть возможность переопределить placement new, но компилятор не симулирует его вызов при определении экземпляра объекта на стеке, хотя, такое поведение было бы логичным;

При размещении экземпляра класса на стеке компилятор сам выделяет память на стеке и инициализирует там экземпляр класса, что примерно равносильно:
Код: plaintext
1.
2.
MyClass* p = (MyClass*)alloca(sizeof(MyClass));
if (NULL != p) new(p) MyClass();

Так почему бы компилятору не создавать placement new по умолчанию, если он не переопределен и не симулировать его вызов? Получили бы более управляемое поведение.

* Можем специализировать шаблоны с дедукцией по параметрам конструктора, но не можем специализировать шаблоны с дедукцией по типу и квалификаторам объявления lvalue;

Есть же using, которые используются подобно typedef! Так почему бы не предусмотреть в них использование cv-квалификаторов c помощью какой-нибудь подходящей семантики? Что-то типа:
Код: plaintext
1.
2.
using MyClassWrapper = MyClass<>;
using const MyClassWrapper = const MyClass<const>;
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39649798
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivТвои представления об объектной модели С++ несколько проще, чем она есть на самом деле.
Помимо константных и неконстантных объектов есть ещё объекты временные, и семантика перемещения, которая работает и с константными, и с неконстантными, и с временными объектами.

Тебе надо ОТДЕЛЬНО, ОРТОГОНАЛЬНО К КОНСТАНТНОСТИ ОБЪЕКТА реализовать эту фичу:
твой объект должен хранить либо ссылку на константу либо реальное значение, и знать, на что он ссылается в данный момент.

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

если эта строка меняется внутри данного объекта, то менять её на ссылку на константные ресурсы либо на реальное значение.

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

И сделать это, кажется, достаточно просто, нужно хранить внутри

std::variant< std::string, std::string_view >

Я не знаю всю твою семантику, но похоже, что тебе это подойдёт, при этом не нужно делать почти вообще ничего.
Я, пока что, отказался от мысли реализовать эту бредовую идею прямо сейчас, но для себя решил плясать от обратного - если константное значение находится в памяти модуля процесса и выделенная под него память read-only, то инициализировать без копирования и хранить этот признак в std::map, на который будет указывать статический указатель внутри protected виртуального метода. Просто сейчас лень штудировать MSDN на предмет всех этих плясок вокруг получения информации о страницах памяти модуля, так как сейчас нет крайней необходимости работы с большими строками или блобами.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39649808
Фотография NekZ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devПри размещении экземпляра класса на стеке компилятор сам выделяет память на стеке и инициализирует там экземпляр класса, что примерно равносильно :
Код: plaintext
1.
2.
MyClass* p = (MyClass*)alloca(sizeof(MyClass));
if (NULL != p) new(p) MyClass();



Спасибо, поржал
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39649823
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NekZСпасибо, поржал На , еще поржи! :)
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39649863
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NekZrdb_devПри размещении экземпляра класса на стеке компилятор сам выделяет память на стеке и инициализирует там экземпляр класса, что примерно равносильно ...
Спасибо, поржал Или ты мне хочешь рассказать, как компилятор вставляет машинный код, оперирующий регистрами (R/E)SP и (R/E)BP? Не стОит!... Ровно тоже самое делает функция _malloca.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39649882
Фотография NekZ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devИли ты мне хочешь рассказать, как компилятор вставляет машинный код, оперирующий регистрами (R/E)SP и (R/E)BP? Не стОит!... Ровно тоже самое делает функция _malloca.


Расскажи-ка тогда, почему при /O2 кода больше с alloca?

Код здорового человека
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
struct MyClass{ int x; MyClass() { x = rand(); } int f() { return x; } };

int main()
{
    MyClass b;
    return b.f();
}



Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
EXTRN   rand:PROC
main    PROC                                            ; COMDAT
        jmp      rand
main    ENDP
MyClass::f, COMDAT PROC
        mov      eax, DWORD PTR [rcx]
        ret      0
MyClass::f ENDP
MyClass::MyClass, COMDAT PROC
        push     rbx
        sub      rsp, 32              ; 00000020H
        mov      rbx, rcx
        call     rand
        mov      DWORD PTR [rbx], eax
        mov      rax, rbx
        add      rsp, 32              ; 00000020H
        pop      rbx
        ret      0
MyClass::MyClass ENDP


Против
Код курильщика
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
struct MyClass{ int x; MyClass() { x = rand(); } int f() { return x; } };

int main()
{
    MyClass* p = (MyClass*)alloca(sizeof(MyClass));
    if (NULL != p) new(p) MyClass();
    return p->f();
}



Код: plaintext
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.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
EXTRN   rand:PROC
EXTRN   __GSHandlerCheck:PROC
EXTRN   __security_check_cookie:PROC
__$ArrayPad$ = 0
main    PROC                                            ; COMDAT
        push     rbp
        sub      rsp, 48              ; 00000030H
        lea      rbp, QWORD PTR [rsp+32]
        mov      QWORD PTR [rbp+32], rbx
        mov      rax, QWORD PTR __security_cookie
        xor      rax, rbp
        mov      QWORD PTR __$ArrayPad$[rbp], rax
        mov      eax, DWORD PTR [rsp]
        sub      rsp, 16
        lea      rbx, QWORD PTR [rsp+32]
        mov      ecx, DWORD PTR [rbx]
        test     rbx, rbx
        je       SHORT $LN12@main
        call     rand
        mov      DWORD PTR [rbx], eax
$LN12@main:
        mov      eax, DWORD PTR [rbx]
        mov      rcx, QWORD PTR __$ArrayPad$[rbp]
        xor      rcx, rbp
        call     __security_check_cookie
        mov      rbx, QWORD PTR [rbp+32]
        lea      rsp, QWORD PTR [rbp+16]
        pop      rbp
        ret      0
main    ENDP
MyClass::f, COMDAT PROC
        mov      eax, DWORD PTR [rcx]
        ret      0
MyClass::f ENDP
MyClass::MyClass, COMDAT PROC
        push     rbx
        sub      rsp, 32              ; 00000020H
        mov      rbx, rcx
        call     rand
        mov      DWORD PTR [rbx], eax
        mov      rax, rbx
        add      rsp, 32              ; 00000020H
        pop      rbx
        ret      0
MyClass::MyClass ENDP
void * __ptr64 __cdecl operator new(unsigned __int64,void * __ptr64) PROC                       ; operator new, COMDAT
        mov      rax, rdx
        ret      0
void * __ptr64 __cdecl operator new(unsigned __int64,void * __ptr64) ENDP                       ; operator new
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39649914
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NekZ, какая, в данном случае разница, больше кода или меньше или откуда берётся код, выделяющий память на стеке - из библиотечной функции, встроенной функции или, собственно, вставляется компилятором? Речь идёт о ПРИНЦИПАХ размещения и инициализации экземпляра класса на стеке. Нафига тут твои детали, которые к этим принципам никакого прямого отношения не имеют?
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39649921
Фотография NekZ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devNekZ, какая, в данном случае разница, больше кода или меньше или откуда берётся код, выделяющий память на стеке - из библиотечной функции, встроенной функции или, собственно, вставляется компилятором? Речь идёт о ПРИНЦИПАХ размещения и инициализации экземпляра класса на стеке. Нафига тут твои детали, которые к этим принципам никакого прямого отношения не имеют?
Точно того ты мог добиться безо всяких аллокаов
Код: plaintext
1.
2.
3.
    char buf[sizeof(MyClass)];
    MyClass* p = (MyClass*)buf;
    new(p) MyClass();


Сдаётся мне, ты просто хочешь поспорить.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39649929
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NekZТочно того ты мог добиться безо всяких аллокаов
Код: plaintext
1.
2.
3.
    char buf[sizeof(MyClass)];
    MyClass* p = (MyClass*)buf;
    new(p) MyClass();


Сдаётся мне, ты просто хочешь поспорить.Мог! И что дальше? Речь не о способе выделения памяти.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39650060
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
* Есть возможность "сказать" new const Type(), но нет возможности этот const хоть как-то "услышать" в реализации перегруженного оператора new, конструктора или деструктора класса;

Оператор NEW выделяет память под объект. Как думаешь, памяти всё равно, какой объект в ней лежит, изменяемый или нет?
Всё равно. Должен operator new зависеть от константности объекта, под который выделяется память ? Нет, не должен.

авторЗачем возможность писать const, если при создании экземпляра класса в куче этот const, ровным счётом, ни на что не влияет?


Ты сможешь этот объект привязать только к константной ссылке или константному указателю , и объект после создания не будет меняться.


* Есть возможность переопределить placement new, но компилятор не симулирует его вызов при определении экземпляра объекта на стеке, хотя, такое поведение было бы логичным;

placement new -- это способ вызвать конструтор и осуществить инициализацию нового объекта в данной памяти.
Создание объекта состоит из двух фаз:
выделяется память под объект каким-либо образом

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

На стеке (auto память) это происходит так:

выделяется память под объект путём резервирования места определённого объёма в стеке.

с помощью вызова конструктора там инициализируется объект.
placement new делает РОВНО второй пункт этого плана, т.е. при создании объекта на стеке именно как раз "эмулируется placement new", так что что тебе ещё надо от С++, не понятно.


* Можем специализировать шаблоны с дедукцией по параметрам конструктора, но не можем специализировать шаблоны с дедукцией по типу и квалификаторам объявления lvalue;

При создании объекта и удалении объекта объект должен быть изменён, в этом суть инициализации.
Объект сначала находится в неинициализированном состоянии, вызывается конструктор, и содержимое объекта меняется таким образом, что объект находится уже в инициализированном состоянии. Ключевое тут -- что меняется. ЭТо значит, что не смотря ни на какие квалификаторы, используемые при определении нового объекта, он ОБЯЗАН поменяться. Т.е. квалификаторы не должны и не могут работать в конструкторе. То же самое можно сказать и про разрушение объекта и деструктор.

Ну и на самом деле (если подумать) квалификаторами обладают не сами объекты, а ссылки на них (в любом виде).
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39650064
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NekZrdb_devПри размещении экземпляра класса на стеке компилятор сам выделяет память на стеке и инициализирует там экземпляр класса, что примерно равносильно :
Код: plaintext
1.
2.
MyClass* p = (MyClass*)alloca(sizeof(MyClass));
if (NULL != p) new(p) MyClass();



Спасибо, поржал

Не, ну он всё верно расписал, именно это и делается. Можно даже такое самому руками делать.
Если ты только не ржал над тем, что он не додумал, что это и есть эмуляция placement new, то ржал ты зря.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39650073
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivНа стеке (auto память) это происходит так:
выделяется память под объект путём резервирования места определённого объёма в стеке.

с помощью вызова конструктора там инициализируется объект.
placement new делает РОВНО второй пункт этого плана, т.е. при создании объекта на стеке именно как раз "эмулируется placement new", так что что тебе ещё надо от С++, не понятно.
В моем понимании, "эмуляция placement new" это когда компилятор создает код вызова placement new независимо от того, создана ли реализация этого оператора компилятором по умолчанию (по моему, она до сих пор не создается по умолчанию и компилятор инициализирует экземпляр на стеке просто пиная конструктор) или же разработчик сделал эту реализацию самостоятельно.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39650080
Фотография NekZ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivНе, ну он всё верно расписал, именно это и делается. Можно даже такое самому руками делать.
Если ты только не ржал над тем, что он не додумал, что это и есть эмуляция placement new, то ржал ты зря.
Ну как сказать. Я поржал над тем, что это данный товарищ посчитал создание объекта на стеке с прямым вызовом аллоки и placement new. С точки зрения результата выполнения кода, наверное, да, это равнозначно, но то, что происходит под капотом, совсем другое, что и было проиллюстрировано выше под спойлерами. Перед вызовом call передвигается sp на размер фрейма вниз, в то время как вызов аллоки двигает sp вниз уже внутри самой функции, т.е. после call и выполняет кучу ненужной работы, так как размер известен на этапе компиляции, поэтому столько кода и нагенерилось ненужного.
По той же логике можно точно так же сказать что удаление гланд через ж0пу и через рот -- вещи равнозначные.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39650086
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NekZНу как сказать. Я поржал над тем, что это данный товарищ посчитал создание объекта на стеке с прямым вызовом аллоки и placement new. С точки зрения результата выполнения кода, наверное, да, это равнозначно, но то, что происходит под капотом, совсем другое, что и было проиллюстрировано выше под спойлерами.Я не хуже тебя знаю, что происходит под капотом. Ты тут не один "знаток" ассемблера и оптимизации машинного кода.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39650100
Фотография NekZ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devЯ не хуже тебя знаю, что происходит под капотом. Ты тут не один "знаток" ассемблера и оптимизации машинного кода.
Разве ты не понял в чём суть?
В этом.
rdb_devТак почему бы компилятору не создавать placement new по умолчанию, если он не переопределен и не симулировать его вызов? Получили бы более управляемое поведение.
Ещё раз смотрим в код здорового человека и не видим там operator new, в отличие от нижележащего. Компилятру не нужно это разбивать на отдельные фазы выдениеня памяти на стеке и вызова конструктора через placement new -- это лишние вызовы. Он делает как можно короче и так как он считает нужным.

P.S. Забавно, что clang с этим примером справляется лучше VS'а.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39650495
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NekZКомпилятру не нужно это разбивать на отдельные фазы выдениеня памяти на стеке и вызова конструктора через placement new -- это лишние вызовы. Он делает как можно короче и так как он считает нужным.То есть компилятор не формирует код для расширения кадра стека при объявлении там экземпляра класса? Это делает конструктор объекта?
Фактически мы всё равно имеем "отдельные фазы" - отдельно расширение кадра стека и отдельно вызов конструктора, точно также, как отдельные фазы оператора new - отдельно выделение памяти из кучи и отдельно вызов конструктора.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39650514
Фотография NekZ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devТо есть компилятор не формирует код для расширения кадра стека при объявлении там экземпляра класса? Это делает конструктор объекта?

Формирует, так и есть.

rdb_devФактически мы всё равно имеем "отдельные фазы" - отдельно расширение кадра стека и отдельно вызов конструктора, точно также, как отдельные фазы оператора new - отдельно выделение памяти из кучи и отдельно вызов конструктора.
А вот здесь не факт, ведь если бы ты попробовал посмотреть что делают clang или gcc с тем же кодом:
Код: plaintext
1.
2.
main:
  jmp rand
Никаких вызовов оператора new. Вообще вызовов. Потому что будь оно так как ты хочешь, то мы бы лишились многих важных оптимизаций, приводящих именно к такому сгенеренному коду. И пример с MSVC компилятором это иллюстрирует наглядно.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39650739
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NekZ, какая разница, как выглядит вызов, если точкой возврата всё равно будет адрес, запихнутый в стек крайним перед передачей управления на первую команду конструктора или чего-то там еще? Ты можешь вызвать привычно через call, запихать адрес возврата и пнуть через jmp, а можешь извратится, запихать в стек адрес, на который хочешь передать управление и сделать ret. В чем разница-то? Принципиально мы всё равно имеет два этапа - выделение памяти и вызов конструктора.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39650790
Фотография NekZ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_dev,

Да, два этапа, только если компилятор считает, что не нужно делать никакого call'а, он не будет его делать
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
struct MyClass{ int x; MyClass() { x = rand(); } int f() { return x; } };

int main()
{
    MyClass b;
    return b.f();
}


clang и gcc сжали это в
Код: plaintext
1.
2.
main:
    jmp rand
Никакого call'а конструктора, никакого адреса возврата на стеке, просто тупой переход в ту функцию с тем же неизменным стеком.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39650855
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NekZrdb_dev,

Да, два этапа, только если компилятор считает, что не нужно делать никакого call'а, он не будет его делать
[src c++]
struct MyClass{ int x; MyClass() { x = rand(); } int f() { return x; } };

int main()
{
MyClass b;
return b.f();
}

clang и gcc сжали это в
Код: plaintext
1.
2.
main:
    jmp rand
Никакого call'а конструктора, никакого адреса возврата на стеке, просто тупой переход в ту функцию с тем же неизменным стеком.С чего ты взял, что перед вызовом jmp на стеке нет адреса возврата из main, который позволяет, в данном случае, делать ret из метода MyClass::f() прямо в точку вызова main возвращая тот же int? Глянь-ка отладчиком!
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39650864
Фотография NekZ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devС чего ты взял, что перед вызовом jmp на стеке нет адреса возврата из main, который позволяет, в данном случае, делать ret из метода MyClass::f() прямо в точку вызова main возвращая тот же int? Глянь-ка отладчиком!
С того, что я привык верить своим глазам. И та заглушка, которая была добавлена линковщиком (аля _start) в счёт не идёт, тупой редирект на другую функцию и больше ничего. Совсем ничего.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39650893
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NekZrdb_devС чего ты взял, что перед вызовом jmp на стеке нет адреса возврата из main, который позволяет, в данном случае, делать ret из метода MyClass::f() прямо в точку вызова main возвращая тот же int? Глянь-ка отладчиком!
С того, что я привык верить своим глазам. И та заглушка, которая была добавлена линковщиком (аля _start) в счёт не идёт, тупой редирект на другую функцию и больше ничего. Совсем ничего.Конечно тупой редирект! Что же еще? Если функция возвращает тот же самый тип и является результатом main, то из main будет именно тупой "редирект" на MyClass::f(), так как адрес возврата из main уже на стеке, которым и воспользуется ret внутри f(), чтобы вернуть значение main в точку вызова. Это оптимизация данного конкретного случая.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39650912
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NekZ, хотя, скорее всего, адрес в jmp указывает непосредственно на библиотечную функцию rand(), а не на MyClass::f(). Компилятор решил, что в данном случае ни экземпляр MyClass, ни его метод f() вообще не нужны.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39650944
Фотография NekZ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devКонечно тупой редирект! Что же еще? Если функция возвращает тот же самый тип и является результатом main, то из main будет именно тупой "редирект" на MyClass::f(), так как адрес возврата из main уже на стеке, которым и воспользуется ret внутри f(), чтобы вернуть значение main в точку вызова. Это оптимизация данного конкретного случая.
Да, пример чисто академический, и именно наличие вот таких вот случаев показывает, что именно компилятор сам решает что где и как рассматривать, на какие фазы разбивать такие-то операции с объектами, а в каких случаях можно всё заинлайнить, не добавляя лишний вызов, в каких случаях вообще всё выбросить как dead code и т.д. Такие решения принимаются в том числе ещё и на основе целевой архитектуры и многих других факторов.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39650945
Фотография NekZ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devNekZ, хотя, скорее всего, адрес в jmp указывает непосредственно на библиотечную функцию rand(), а не на MyClass::f(). Компилятор решил, что в данном случае ни экземпляр MyClass, ни его метод f() вообще не нужны.
Я до тебя это и пытаюсь донести.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39651050
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devВ моем понимании, "эмуляция placement new" это когда компилятор создает код вызова placement new независимо от того, создана ли реализация этого оператора компилятором по умолчанию (по моему, она до сих пор не создается по умолчанию и компилятор инициализирует экземпляр на стеке просто пиная конструктор) или же разработчик сделал эту реализацию самостоятельно.

0) placement new не переопределяется.
1) код placement new -- это вызов констуктора с указанным placement-у указателем на память в виде this .
2) соответственно, код placement new всегда инлайнится. Это собственно один вызов функции.

Что тебе ещё надо эмулировать?
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39651052
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NekZMasterZivНе, ну он всё верно расписал, именно это и делается. Можно даже такое самому руками делать.
Если ты только не ржал над тем, что он не додумал, что это и есть эмуляция placement new, то ржал ты зря.
Ну как сказать. Я поржал над тем, что это данный товарищ посчитал создание объекта на стеке с прямым вызовом аллоки и placement new. С точки зрения результата выполнения кода, наверное, да, это равнозначно, но то, что происходит под капотом, совсем другое, что и было проиллюстрировано выше под спойлерами. Перед вызовом call передвигается sp на размер фрейма вниз, в то время как вызов аллоки двигает sp вниз уже внутри самой функции, т.е. после call и выполняет кучу ненужной работы, так как размер известен на этапе компиляции, поэтому столько кода и нагенерилось ненужного.
По той же логике можно точно так же сказать что удаление гланд через ж0пу и через рот -- вещи равнозначные.

Что то ты тут намутил. Он всё там вполне адекватно расписал и дал эквивалентный код.
Другое дело, что код этот нафиг не нужен, поскольку можно просто написать автоматическую переменную этого класса.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39651053
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NekZrdb_devЯ не хуже тебя знаю, что происходит под капотом. Ты тут не один "знаток" ассемблера и оптимизации машинного кода.
Разве ты не понял в чём суть?
В этом.
rdb_devТак почему бы компилятору не создавать placement new по умолчанию, если он не переопределен и не симулировать его вызов? Получили бы более управляемое поведение.
Ещё раз смотрим в код здорового человека и не видим там operator new, в отличие от нижележащего. Компилятру не нужно это разбивать на отдельные фазы выдениеня памяти на стеке и вызова конструктора через placement new -- это лишние вызовы. Он делает как можно короче и так как он считает нужным.

P.S. Забавно, что clang с этим примером справляется лучше VS'а.

Ещё раз, ваш чисто теоретический спор лишён всякого смысла, поскольку все вызовы всего кода создания чего-то на стеке и потом вызова констуктора инлайнятся.
Абсолютно по барабану, как это всё происходит.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39651071
Фотография NekZ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivЕщё раз, ваш чисто теоретический спор лишён всякого смысла, поскольку все вызовы всего кода создания чего-то на стеке и потом вызова констуктора инлайнятся.
Абсолютно по барабану, как это всё происходит.
Я об этом ниже написал, переходя от голой теории к конкретике.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39651076
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NekZMasterZivЕщё раз, ваш чисто теоретический спор лишён всякого смысла, поскольку все вызовы всего кода создания чего-то на стеке и потом вызова констуктора инлайнятся.
Абсолютно по барабану, как это всё происходит.
Я об этом ниже написал, переходя от голой теории к конкретике.

Ну и?
Топик закрываю?
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39651096
Фотография NekZ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivНу и?
Топик закрываю?
ТСу решать
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39651161
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NekZMasterZivЕщё раз, ваш чисто теоретический спор лишён всякого смысла, поскольку все вызовы всего кода создания чего-то на стеке и потом вызова констуктора инлайнятся.
Абсолютно по барабану, как это всё происходит.
Я об этом ниже написал, переходя от голой теории к конкретике.Если переходить к конкретике, то в твоём примере никакой экземпляр класса вообще не создается - нигде, а компилятор на -O3 заменяет метод объекта и его член-переменную функциональным эквивалентом, т.е., просто фигачит jmp на rand() из main.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39651162
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivНу и?
Топик закрываю?В общем-то, перетёрли уже всё, что только можно было перетереть и "в" и "около". Закрывай, коль надоела эта байда.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39651166
Фотография NekZ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devЕсли переходить к конкретике, то в твоём примере никакой экземпляр класса вообще не создается - нигде, а компилятор на -O3 заменяет метод объекта и его член-переменную функциональным эквивалентом, т.е., просто фигачит jmp на rand() из main.
Хе-хе, так в том-то и была суть всего, что я тебе талдычу уже третью страницу топика.
Да даже на -O1 останется лишь jmp.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39651171
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NekZХе-хе, так в том-то и была суть всего, что я тебе талдычу уже третью страницу топика.
Да даже на -O1 останется лишь jmp.Told'ычить-то ты, конечно, told'ычишь, но объекта как не было, так и нет, а мы говорим именно об объектах.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39651172
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZiv0) placement new не переопределяется.
1) код placement new -- это вызов констуктора с указанным placement-у указателем на память в виде this .
2) соответственно, код placement new всегда инлайнится. Это собственно один вызов функции.Да брось! Всё прекрасно переопределяется:
Код: plaintext
1.
2.
3.
4.
void* operator new(size_t size, void *p)
{
  return p;
}
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39651190
Фотография NekZ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devTold'ычить-то ты, конечно, told'ычишь, но объекта как не было, так и нет, а мы говорим именно об объектах.
В терминал языка ассемблера вообще объектов нет, это чисто тот удобный фасад для программистов чтобы они не видели всю поднаготную. И именно такие вот оптимизации, выкидывающие вообще всякие там упоминания о твоём классе и его мемберах из итогового ассемблера, демонстрируют тебе, что нет никаких фаз выделения памяти на стеке и вызова placement new , они существуют только в твоём сознании.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39651192
Фотография NekZ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NekZ,

В терминах*
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39651327
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NekZВ терминал языка ассемблера вообще объектов нет, это чисто тот удобный фасад для программистов чтобы они не видели всю поднаготную.Объектов нет не в терминах ассемблера, а в терминах машинных кодов, а в терминах ассемблера он вполне себе существует и, причем, с виртуальными методами. Например, в TASM.

NekZИ именно такие вот оптимизации, выкидывающие вообще всякие там упоминания о твоём классе и его мемберах из итогового ассемблера, демонстрируют тебе, что нет никаких фаз выделения памяти на стеке и вызова placement new , они существуют только в твоём сознании.Да что ты говоришь? Попробуй-ка при при максимальной оптимизации добавить квалификатор volatile к объявлению метода MyClass::f*(), к объявлению экземпляра класса собери и удивись "силе моего сознания".
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39651334
Фотография NekZ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devДа что ты говоришь? Попробуй-ка при при максимальной оптимизации добавить квалификатор volatile к объявлению метода MyClass::f*(), к объявлению экземпляра класса собери и удивись "силе моего сознания".
Давай.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
#include <cstdlib>
#include <new>
#include <malloc.h>

struct MyClass{ int x; MyClass() { x = rand(); } int f() volatile { return x; } };

int main()
{
    volatile MyClass foo;
    return foo.f();
}



clang -O3
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
main: # @main
  push rax
  call rand
  mov dword ptr [rsp + 4], eax
  mov eax, dword ptr [rsp + 4]
  pop rcx
  ret
Где выделение памяти под объект?
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39651344
Leonid Kudryavtsev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NekZГде выделение памяти под объект?

push rax


?
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39651349
Фотография NekZ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Leonid KudryavtsevNekZГде выделение памяти под объект?

push rax


?
Нет, это пушится адрес возврата для последующей инструкции call
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39651360
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NekZНет, это пушится адрес возврата для последующей инструкции callЛеонид абсолютно прав!
"push rax" расширяет стек вниз на 8 байт, сохраняя там значение из "rax", что равносильно (в нотации Intel):
Код: asm
1.
2.
sub rsp, 8
mov dword ptr [rsp], rax

Обычно, компилятор примерно так и делает, но в данном, конкретном случае, расширение кадра невелико и компилятор, почему-то, выбрал "push rax" с инициализацией памяти на стеке из регистра "rax", вместо "sub rsp, 8" без инициализации.
Далее, по соглашению __cdecl, результат функции rand() помещается в регистр "eax" и мнемоника "mov dword ptr [rsp + 4], eax" указывает нам на то, что значение из регистра "eax" помещается, в старшее двойное слово расширенной части кадра стека. Сие нам говорит о том, что компилятор разместил код, расширяющий кадр стека с выравниванием на четверное слово, но, при этом, используется только старшее двойное слово - "MyClass::x", а мнемоника "mov eax, dword ptr [rsp + 4]" говорит нам о том, что в clang квалификатор volatile напрочь отключает оптимизацию, как таковую, чего не происходит, например, в гнусе.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39651366
Фотография NekZ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_dev,

Да, что-то я забыл совсем, что о адресе возврата уже call сам заботится. Это если jmp юзать для вызова в новом кадре, то потребуются push и pop. А вот, кстати и ответ
wikipediaSince GCC version 4.5, the stack must be aligned to a 16-byte boundary when calling a function (previous versions only required a 4-byte alignment.)

push используется для CPU со stack engine как и последующие два mov'а, типа так более эффективно.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39651403
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NekZ, только мне непонятно зачем делать push/pop, когда после любой операции модификации "rsp" для выравнивания вполне достаточно сделать "and rsp, -16".
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39651417
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Чтобы немного разбавить офтопик, небольшая ссылка по теме :)
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0847r0.html
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39651583
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly Moskovsky, если я правильно понимаю написанное, парни предлагают различать то, через что осуществляется доступ к членам/методам экземпляра класса (объекта) - через lvalue-ссылку или же через rvalue-ссылку с учётом cv-квалификаторов, а также использовать "this" в объявлении параметров метода в качестве ключевого слова для указания того, что дедукция шаблона должна осуществляться по типу lvalue/rvalue ссылки, через которую осуществляется доступ и, опять же, с учётом cv-квалификаторов.

Похоже, я не одинок в своих хотелках!
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39651640
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devпредлагают различать то, через что осуществляется доступ к членам/методам экземпляра класса (объекта) - через lvalue-ссылку или же через rvalue-ссылку с учётом cv-квалификаторов
Это уже есть начиная с С++11.
А остальное - да, предлагают.
...
Рейтинг: 0 / 0
Константный экземпляр класса. Кто как делает?
    #39651665
teo609
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly Moskovsky,

спасибо за ссылку.
...
Рейтинг: 0 / 0
94 сообщений из 94, показаны все 4 страниц
Форумы / C++ [игнор отключен] [закрыт для гостей] / Константный экземпляр класса. Кто как делает?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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