LINUX.ORG.RU

c++ статическая константа

 


0

2

Добрый вечер, подскажите, почему вот такая инициализация статической константы проходит

class A {
static const int some_size = 4;
}

а вот такая вот нет

class B {
static const QString someStr = "Ololo";
}



Последнее исправление: da17 (всего исправлений: 1)

Потому что значение должно быть известно на этапе компиляции

anonymous
()

Потому-что QString не тривиальный тип, используй static inline.

anonymous
()

О, это та ещё наркомания, на удивление никто из ононов внятно так и не ответил, ближе всех к истине был первый. Все static переменные должны быть готовы к использованию «до начала выполнения программы», т.е. если её значение не задано, будет 0, если задано чемто простым аля int, значение сразу и подставится, если требуется более хитрая инциализация, она должны быть выполненна до динамических инциализаций. В твоём случае ты пытаешся инициализировать переменную внутри объявления класса, т.е. в любой единице трансляции куда ты заинклудишь свой header, но всё изменится если ты вынесешь инициализацию в отдельное определение

class A {
		const static QString aaa;
};

const QString A::aaa = "aaa";

Чёт какойто бред получился, но может укажет направление

sparks ★★★★
()

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

в первом случае возможно какое-то послабление для тривиальных типов, но может ты смотришь на какое-то расширение компилятора. попробуй включить -pedantic, есть предположение, что static const компилятор трансформировал в static constexpr который автоматически подразумевает inline.

anonymous
()
Ответ на: комментарий от da17

не знаком с брюсом. может быть компилятор это как-то выоптимизировал. static const int хранить в памяти вообще не надо, его можно просто заменить на значение 4 в тех местах где он используется, т.е. возможно компилятор на этапе компиляции просто вычислил значение (ака constexpr) и удалил этот мембер навсегда. а QString хранить где-то в памяти уже надо и на этапе компиляции его значение не вычисляется.

anonymous
()

Потому, что никто не удосужился объявить constexpr конструктор для QString, а компилятор сам посчитал что существующий конструктор QString не может считаться constexpr.

Kroz ★★★★★
()
Ответ на: комментарий от da17

Анон же выше дал ссылку на стандарт. Инициализатор при объявлении статических членов можно писать только для констант целочисленных типов (для constexpr можно больше).

xaizek ★★★★★
()

Меня бы другой вопрос беспокоил - а будет ли глобальная QString правильно проинициализирована в принципе? Сложнее базовых типов в статик не кладу (статик в функции не в счет), если тип сложнее, то возвращаю его из функции. Наверное, все должно правильно работать, если модуль с реализацией QString в разделяемой либе, но никто этого не гарантирует, а может ты слинкуешься со статической. Я в общем рассуждаю, о некотором сложном типе, который может зависить от каких-то глобальных объектов, возможно это не QString.

pavlick ★★
()
Последнее исправление: pavlick (всего исправлений: 1)
Ответ на: комментарий от pavlick

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

sparks ★★★★
()
Ответ на: комментарий от pavlick

Ты даже не понимаешь о чем я, сбавь тон, а то будешь выглядеть идиотом.

Только хотел ответить ему в том же стиле. По поводу вопроса - в таком виде можно инициализировать QString, будет конвертация из UTF-8 в UCS-2, реализация внутри Qt, не требует инициализации и/или глобальных переменных.

anonymous
()
Ответ на: комментарий от anonymous

У тебя есть шанс, тем более что вопрос был в другом, реализация механизма работы статических / динамических библиотек лежит на ОС и частично компиляторе, вопрос об инциализации сложного объекта покрывается описанием «Динамической инициализации» в стандарте плюсов, а это значит обеспечить всё необходимое для инициализации сложного объекта это забота компилятора и ОС

sparks ★★★★
()
Ответ на: комментарий от cloun1902

Порядок инициализации неглобальных (те что блок скоуп) прописан явно - будут проинициализированы однажды и потокобезопасно, когда какой-нибудь поток зайдет в этот скоуп. Деинициализация в обратном порядке. А глобальные хз как, как карта ляжет (глобальные переменные с разных модулей, в одном модуле - в порядке definitions).

pavlick ★★
()
Последнее исправление: pavlick (всего исправлений: 2)
Ответ на: комментарий от pavlick

ммм, попробую вежливо, боюсь Сер, ваш ответ содержит неокторые технические неточности, в частности вы путаете Области видимости и Срок жизни перменных, переменные которые инициализируются однажды это как раз Static, но статик не определяет Область видимости, т.е. не делает перменную Глобальной, коментировать про скопы потоков я пожалуй не стану

sparks ★★★★
()
Ответ на: комментарий от pavlick

Вот оно что. Я думал ты сейчас раскажешь про, например, дублирование статиков в классах на dlopen-е. А ты просто нужный порядок зафорсить не осилил.

А глобальные хз как, как карта ляжет.

За букварь. https://en.cppreference.com/w/cpp/io/ios_base/Init

cloun1902
()
Ответ на: комментарий от cloun1902

И? При чем здесь std::ios_base::Init? Ты хочешь сказать, что подинклудив iostream, я управляю порядком инициализации между main и какой-нибудь libm.a?

pavlick ★★
()
Ответ на: комментарий от pavlick

И … это пример, который множит на ноль твою потугу

А глобальные хз как, как карта ляжет (глобальные переменные с разных модулей, в одном модуле - в порядке definitions)

#include <iostream>

// здесь std::cout и ko проинициализированно инфа сотка
cloun1902
()
Ответ на: комментарий от cloun1902

При чем здесь cout? Ладно, с тобой всё ясно, в черный список. Может я бы попытался тебе что-то объяснить если бы не твоё хамское поведение.

pavlick ★★
()
Ответ на: комментарий от pavlick

А с тобой весело, ты не злись, мне просто работать не оч хочется сегодя и я сюда прокрастинирую, твой пример с глобальным скопом, вообще ничего не показывает, ты хочешь сказать что класс s стал «внезапно» доступен из всех единиц трасляции?

sparks ★★★★
()

Надеюсь, что это просто два дешевых заднеприводных тролля, а не реальные плюсовики.

pavlick ★★
()
Ответ на: комментарий от pavlick

Чую скоро минуса придут)) но кринж знатный вышел, ни о чем не жалею

sparks ★★★★
()

Балаболка слилась полность. Ну тогда для пацанов. Показываю, в чём минус данной схемы:

$ cat main2.cc
#include <iostream>

void f() { std::cout << "дошколёнок\n"; }
$ cat main.cc
void f();
struct S { S() { f(); } } s;
int main() {}
$ g++ main.cc main2.cc && ./a.out
Segmentation fault (core dumped)

Фиксим:

$ cat main2.cc
#include <iostream>

void f() { std::cout << "дошколёнок\n"; }
$ cat main.cc
#include <iostream> // <== инитим cout

void f();
struct S { S() { f(); } } s;
int main() {}
$ g++ main.cc main2.cc && ./a.out
дошколёнок

Всё просто.

cloun1902
()

Админы, запилить бы такое - ник ингнорируемых юзеров писать красным, например. Не очень удобно ходить каждому в профиль и смотреть в игноре он или нет. Удобно с ходу понимать что это за пассажир и стоит ли с ним вообще говорить начинать.

pavlick ★★
()
Ответ на: комментарий от pavlick

Что ещё ожидать от идиота с Павликом морозовым на аве

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.