Здравствуйте, Shmj, Вы писали:
S>Имеем constexpr в конструкторе и const при создании — но выделяются разные участки памяти. Зачем? Сложно проверить и для всех таких constexpr/constexpr не выделять память по 100 раз?
test.java
const start = new Date();
// какие то вычисления...const end = new Date();
System.out.println("Elapsed: " + (end - start)); // Упс ((
Здравствуйте, sergeya, Вы писали:
S>>Имеем constexpr в конструкторе и const при создании — но выделяются разные участки памяти. Зачем? Сложно проверить и для всех таких constexpr/constexpr не выделять память по 100 раз?
S>test.java
error: illegal start of expression
const start = new Date();
что то похожее на constexpr есть в выражениях разрешенных в значениях аннотаций и там нельзя new Date() конечно
Здравствуйте, Shmj, Вы писали:
S>Никаким паттерном ты этого не решишь. Можно создать объект и после этого проверить если уже такой существует в словаре — то не включать в словарь повторно. Но для этого придется сначала создать и выполнять проверки на этапе выполнения.
Так уж и быть. Вот тебе в качестве иллюстрации идеи:
Обрати внимание, совсем не обязательно объявлять конструктор constexpr. Этот конструктор вообще можно выкинуть, всё будет работать и без него.
Повторюсь, это лишь иллюстрация идеи — самая примитивная, самая "лобовая". Это идею можно обыграть на сотни вариантов — с многопоточностью, с управляетмым временем жизни, со смартпоинтерами, без смарт-поинтеров, можно использовать оберточные классы и функции и т.д. и т.п. — в зависимости от конкретных условий применения.
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, пффф, Вы писали:
S>>Хорошо, покажите как создавать константные объекты. Может я не правильно создаю?
П>Никак. С любого объекта можно снять константность.
На самом деле, можно создать константный объект и в динамической памяти:
const MyClass* obj1 = new const MyClass(5);
Снятие константности с такого объекта и использование его как неконстантного порождает неопределённое поведение.
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, rg45, Вы писали:
П>>Никак. С любого объекта можно снять константность.
R>На самом деле, можно создать константный объект и в динамической памяти:
R>
R>const MyClass* obj1 = new const MyClass(5);
R>
Можно. Но зачем?
R>Снятие константности с такого объекта и использование его как неконстантного порождает неопределённое поведение.
Хм. Не знал. Впрочем, никогда на куче константные объекты не создавал. А почему тут UB?
Здравствуйте, пффф, Вы писали:
П>Хм. Не знал. Впрочем, никогда на куче константные объекты не создавал. А почему тут UB?
Ну это общее требование стандарта к константным объектам, независимо от области их обитания. Наверное, оставляют разработчикам компиляторов больше возможностей для оптимизаций.
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, rg45, Вы писали:
П>>Хм. Не знал. Впрочем, никогда на куче константные объекты не создавал. А почему тут UB?
R>Ну это общее требование стандарта к константным объектам, независимо от области их обитания. Наверное, оставляют разработчикам компиляторов больше возможностей для оптимизаций.
Ясно. Не обращал внимания на этот нюанс. Как-то редко создавал именно константные объекты, обычно константность привнесенная
Здравствуйте, пффф, Вы писали:
П>Ясно. Не обращал внимания на этот нюанс. Как-то редко создавал именно константные объекты, обычно константность привнесенная
Ну да, я тоже не припоминаю в своей практике, чтоб этим кто-то активно пользовался. Это я упомянул к слову, раз уж затронули эту тему.
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, Shmj, Вы писали:
S>Имеем constexpr в конструкторе и const при создании — но выделяются разные участки памяти. Зачем? Сложно проверить и для всех таких constexpr/constexpr не выделять память по 100 раз? S>Вроде бы мелочь, а открываются колоссальные возможности по оптимизации
Пока во время исполнения нет понятия "абсолютно константные данные", и как следствие, — неразличимые между собой копии, — колоссальные возможности по оптимизации не открываются.
(Во время компиляции они есть, но тоже с оговорками. И вот этот дуализм constexpr, конечно, вносит сумятицу).
А давай не будем далеко ходить.
Вот смотри. Пусть у тебя воистину константа
class Konst {};
const Konst* k1 = new const Konst();
const Konst* k2 = new const Konst();
assert(*k1 == *k2); // эквивалентность значений - это мы и так уже ожидаем
assert(k1 == k2); // идентичность объектов - то, что хочешь внедрить ты
// а теперь страшное!delete k1;
delete k2; // ведь мы сделали два new, - значит, и два delete должны
Да и сам по себе constexpr-конструктор не даёт полной гарантии на неизменность.
struct Var {
int x;
constexpr Var(int a, int b) : x(a+b) {}
};
Var v(1, 2);
v.x += 4;
constexpr-ом мы просто обещаем, что эти функции можно вызывать во время компиляции тоже.
Внезапно, переприсваивать во время компиляции тоже можно.
constexpr Var foo(int a, int b, int c) {
Var v(a, b);
v.x += c;
return v;
}
int bar[foo(1, 2, 4).x]; // тут хочешь не хочешь, а константа времени компиляцииtemplate<Var v> struct Buz {};
Buz<foo(1, 2, 4)> buz; // Buz<Var{.x=7}> // константа времени компиляции
Но и во время компиляции важнейшее свойство объектов — уникальность адресов — никуда не девается.
constexpr Var foo1(int a, int b) {
Var* p = new Var(a, 0); // p->x = a
Var* q = new Var(b, 0); // q->x = b
p->x += q->x; // p->x = a+b q не трогаем, это отдельный объект
q->x += p->x; // q->x = a+b+b
Var v = *q;
delete p; delete q;
return v;
}
Здравствуйте, Shmj, Вы писали:
S>constexpr к конструктору — а как мне еще обозначить что не нужно 100 раз выделять память и хватит одного экземпляра на всю программу для всех. const — конструкторов нет. Поля сделал const. Что еще нужно?
Заведи глобальную именованную константу и обращайся к ней изо всех мест. Делов-то.
struct Konst { int x; int y; int z; }; // у таких структур, кстати, конструкторы из коробки constexpr
// глобальные константыconst Konst abc1{1, 2, 3};
const Konst abc2{1, 2, 3}; // знаю-знаю, тебе вот этого как раз не хочетсяconst Konst def {4, 5, 6};
static_assert(&abc1 != &abc2);
// где-то по месту используешь имена вместо выражений
// ..... abc1 ..... abc1 ..... def ..... def .....
// ну ок, допустим, тебе лень где-то держать эти константы, экспортировать их ещё... но хочется синглетонности.
// внимание, трюк!template<Konst k> struct Storage {
static constexpr Konst instance = k;
};
// используешь выражения сколько угодно разconst Konst& xxx = Storage<Konst{1,2,3}>::instance;
const Konst& yyy = Storage<Konst{1,2,3}>::instance;
static_assert(&xxx == &yyy);
Здравствуйте, Кодт, Вы писали:
К>Заведи глобальную именованную константу и обращайся к ней изо всех мест. Делов-то.
Это не удобно — приходится вручную помнить где какие константы использовались.
Принято что для описания UI — C++ не подходит, лучше XML или что-то такое. А почему? Вот вам пример как чисто получается описать UI на языке программирования с возможностью любых сложных действий, когда требуется. При этом выглядит как декларативное описание и по сути таковым является:
return Scaffold(
appBar: AppBar(
leading: const IconButton(
icon: Icon(Icons.menu),
tooltip: 'Navigation menu',
onPressed: null,
),
title: const Text('Example title'),
actions: const [
IconButton(
icon: Icon(Icons.search),
tooltip: 'Search',
onPressed: null,
),
],
),
// body is the majority of the screen.
body: const Center(
child: Text('Hello, world!'),
),
floatingActionButton: const FloatingActionButton(
tooltip: 'Add', // used by assistive technologies
onPressed: null,
child: Icon(Icons.add),
),
);
Здравствуйте, Кодт, Вы писали:
К>Вот смотри. Пусть у тебя воистину константа К>
К>class Konst {};
К>const Konst* k1 = new const Konst();
К>const Konst* k2 = new const Konst();
К>assert(*k1 == *k2); // эквивалентность значений - это мы и так уже ожидаем
К>assert(k1 == k2); // идентичность объектов - то, что хочешь внедрить ты
К>// а теперь страшное!
К>delete k1;
К>delete k2; // ведь мы сделали два new, - значит, и два delete должны
К>
Когда const char* = "text" — все понимают что удалять нельзя — это норм, потому что все понимают что это настоящая константа.
Но уже понятно что в C++ настоящих констант нет. Возможно и добавят что-то типа immutable лет через 10.
Здравствуйте, Shmj, Вы писали:
S>Когда const char* = "text" — все понимают что удалять нельзя — это норм, потому что все понимают что это настоящая константа.
Это в C# — написал "new" и гуляй, можешь ни о чём больше не заботиться. Язык со встроенными памперсами подберёт за тобой всю срань. Когда-нибудь. А в C++ каждому "new" должен соответствовать свой "delete". И это не вопрос константности.
Все твои посты сводятся к следующему: "не хочу учить С++, хочу писать на нём, как на приятных языках". Только невольно возникает вопрос: чего тебе не сидится на твоих "приятных" языках.
--
Справедливость выше закона. А человечность выше справедливости.