В VS7.1 подобная инициализация неконстантной ссылки (pos) компилируется, временный и безымянный P3f() существует в течение жизни ссылки. Нестандартное решение, но очень хочется — используя ссылки вместо указателей, иметь также все преимущества forward declaration. Вопрос: как это сделать стандартными методами, изящно и эффективно?
В твоем случае объект P3f() живет только до закрывающей скобки pos, т.е. это вообще не решение (даже нестандартное). Вообще-то случай похож на pimpl и напрашивается использование какого-нибудь смарт-указателя.
Да, это нестандартное расширение компиляторов VC.
E> временный и безымянный P3f() существует в течение жизни ссылки.
Ха! И интересно, где же этот безымянный объект существует?
На самом деле, продление жизни объектов по ссылкам действует только вот здесь:
void foo()
{
// локальное хранилище!
Some const/*для VC - необязательно*/ &ref = make_Some_or_something_derived(); // конструктор или функция
.....
.....
.....
}
А во всех остальных случаях временный объект (размещённый, естественно, на стеке) живёт до выхода из полного выражения.
В общем, Sample::Sample() : pos(P3f()) оказался инициализирован мусором.
Тебе просто повезло, что этот участок стека никто не трогал.
E> Нестандартное решение, но очень хочется — используя ссылки вместо указателей, иметь также все преимущества forward declaration.
Чем плохи указатели?
Используй какой-нибудь умный указатель, терпимый к недоопределённым классам (auto_ptr — нетерпим, shared_ptr — подходит).
E> Вопрос: как это сделать стандартными методами, изящно и эффективно?
Твои критерии эффективности? Да и изящества тоже...
Спасибо за ответ! К>А во всех остальных случаях временный объект (размещённый, естественно, на стеке) живёт до выхода из полного выражения. К>В общем, Sample::Sample() : pos(P3f()) оказался инициализирован мусором. К>Тебе просто повезло, что этот участок стека никто не трогал.
Повезло, потому что такой код в наш рабочий проект не помещу по вполне понятным причинам. А в тестовом режиме не удалось вызвать ошибку с инициализацией в конструкторе. Наверное, плохо старался.
К>Чем плохи указатели? К>Используй какой-нибудь умный указатель, терпимый к недоопределённым классам (auto_ptr — нетерпим, shared_ptr — подходит).
ну просто указатели плохи по тем причинам, что ты вспомнил умные, а также каждый раз, делая "p->x = ..." меня пробирает суеверная дрожь (а вдруг NULL?!). Умные недостаточно хороши некоторым усложнением (для меня) кода, ну и насколько могу представить, перегруженная "->" наверное, несколько снизит производительность (конечно, это критично далеко не всегда). Ну и еще, пожалуй, субъективно выражение
l = sqrtf(pos->x*pos->x + pos->y*pos->y + pos->z*pos->z);
мною воспринимается хуже, чем
l = sqrtf(pos.x*pos.x + pos.y*pos.y + pos.z*pos.z);
К>Твои критерии эффективности? Да и изящества тоже...
Здравствуйте, eremeer, Вы писали:
К>>Чем плохи указатели? К>>Используй какой-нибудь умный указатель, терпимый к недоопределённым классам (auto_ptr — нетерпим, shared_ptr — подходит). E>ну просто указатели плохи по тем причинам, что ты вспомнил умные, а также каждый раз, делая "p->x = ..." меня пробирает суеверная дрожь (а вдруг NULL?!). Умные недостаточно хороши некоторым усложнением (для меня) кода, ну и насколько могу представить, перегруженная "->" наверное, несколько снизит производительность (конечно, это критично далеко не всегда). Ну и еще, пожалуй, субъективно выражение E>
l = sqrtf(pos->x*pos->x + pos->y*pos->y + pos->z*pos->z);
мною воспринимается хуже, чем
l = sqrtf(pos.x*pos.x + pos.y*pos.y + pos.z*pos.z);
Увы, в С++ нет ни перегрузки оператора ., ни миксинов — поэтому либо ->, либо ().
P3f хранит три инта? тогда то что выше и есть самый эффективный и изящный вариант.
Зачем тут вообще new и вся вытекающая муть?
Уж такую банальность компилятор соптимизурует в лучшем виде.
И даже если не соптимизирует — копирование трех интов (да хоть сорока даблов) на порядки бестрее new...
страшненько выглядит особенно деструктор. Наверное, так и придется на указателях телегу тянуть...
В твоем случае объект P3f() живет только до закрывающей скобки pos, т.е. это вообще не решение (даже нестандартное). Вообще-то случай похож на pimpl и напрашивается использование какого-нибудь смарт-указателя.
Ага, принял это за рабочее решение, когда смотрел, в какое время вызываются деструкторы, надо было еще на значения посмотреть.
Здравствуйте, Кодт, Вы писали:
К>Тогда самым изящным и эффективным будет поместить туда объект полностью определённого типа (т.е. первый вариант). К>Какие есть препятствия к этому?
структура, наподобие указанной, хранится в здоровенном (около 200кб) заголовочном файле сторонней библиотеки. Мой заголовочный в десятке cpp подключается. В итоге проект на 20 секунд медленнее компилируется (при полной сборке). В проекте сотни три файлов: тут 20 сек, там 30 и получаем вместо 5 минут компиляции, например, 10.
P.S. Люди, собирающие проекты сутками, будут, наверное, смеяться над такими проблемами.
Здравствуйте, Max M., Вы писали: MM>P3f хранит три инта? тогда то что выше и есть самый эффективный и изящный вариант. MM>Зачем тут вообще new и вся вытекающая муть? MM>Уж такую банальность компилятор соптимизурует в лучшем виде. MM>И даже если не соптимизирует — копирование трех интов (да хоть сорока даблов) на порядки бестрее new...
new это ответ по поводу эффективности и изящности (вопрос здесь)
. Т.е. если использовать предварительное объявление P3f, то, скорее всего, придется на указателях, через new делать, а это неэффективно. У меня мало опыта, поэтому подумал: а вдруг есть другой, волшебный способ?
Здравствуйте, eremeer, Вы писали:
E>Здравствуйте, Max M., Вы писали: MM>>P3f хранит три инта? тогда то что выше и есть самый эффективный и изящный вариант. E>new это ответ по поводу эффективности и изящности
А, извини — да (пока до конца дочитал содержание первого поста из головы выветрилось ).
Ну а с precompiled headers экспериментировать не пробовал? — все же есть тут что-то совсем мрачное
— из-за пяти минут времени компиляции жертовать простотой и читабельностью кода...
(эффективность уж ладно — можно прикрыть глаза)
Здравствуйте, Max M., Вы писали:
MM>Ну а с precompiled headers экспериментировать не пробовал? — все же есть тут что-то совсем мрачное
precompiled? где-то выше специально упомянул про полный билд а его приходится иногда делать — слетает отладчик в debug-версии проекта, помогает только полный ребилд (говорят, еще может помочь хирург — выправить руки .
MM>- из-за пяти минут времени компиляции жертовать простотой и читабельностью кода... MM>(эффективность уж ладно — можно прикрыть глаза)
когда сидишь в дебаге — 5 или 10 — разница все-таки есть. (хотя, после посещения хирурга, возможно и не придется корчиться в дебаге...)
Здравствуйте, eremeer, Вы писали:
E> Т.е. если использовать предварительное объявление P3f, то, скорее всего, придется на указателях, через new делать, а это неэффективно. У меня мало опыта, поэтому подумал: а вдруг есть другой, волшебный способ?
Волшебного способа нет. Или компилятор знает размер P3f при компиляции Sample, или нет — тогда только new.
Здравствуйте, eremeer, Вы писали:
E>страшненько выглядит особенно деструктор. Наверное, так и придется на указателях телегу тянуть...
Я НЕ говорил, что так НАДО делать.
В данном случае поведение T& будет весьма близко к T* const, а выставлять член данных в public тоже как-то не комильфо. Хотя согласен, что писать p.x приятнее, p->x и p.x(). Для простых типов из трех int с простой как три копейки семантикой имхо разумнее использовать POD-структуру и не париться, на время компиляции ее полное определение не повлияет.
Здравствуйте, AstroMan, Вы писали:
AM>Я бы сам руки оторвал (и не только руки), если б увидел в проекте. Но вопрос был чисто теоретический. Ну хотелось человеку ссылок и forwarda
пока есть руки, могу написать такое: (тоже теоретически)
Здравствуйте, eremeer, Вы писали:
E>структура, наподобие указанной, хранится в здоровенном (около 200кб) заголовочном файле сторонней библиотеки. Мой заголовочный в десятке cpp подключается. В итоге проект на 20 секунд медленнее компилируется (при полной сборке). В проекте сотни три файлов: тут 20 сек, там 30 и получаем вместо 5 минут компиляции, например, 10.
У тебя есть два выхода
Выход 1
struct StructFromLib;
struct UsefulDataFromStructFromLib {
// Тут собственно описываешь нужные тебе поля
};
// эту функцию реализуешь в ОДНОМ cpp, который собственно и зависит от библиотечного хедераextern UsefulDataFromStructFromLib extractUsefulData( const StructFromLib& );
ну и в своём классе хранишь константную копию UsefulDataFromStructFromLib без всяких ссылок или указателей
Выход 2
struct StructFromLib;
class StructFromLibAccessor {
public:
StructFromLibAccessor( StructFromLib* data_ = 0 ) : data( data_ ) {}
// Тут пишешь аксессоры к нужным тебе полям, дописывая их по мере нуждыint GetField1() const;
double GetField2() const;
void SetField1( int ); // если надо, конечноprivate:
StructFromLib * const data;
};
// Методы StructFromLibAccessor реализуешь в ОДНОМ cpp,
// который собственно и зависит от библиотечного хедера
Ну и в своём классе хранишь просто поле StructFromLibAccessor.
E>P.S. Люди, собирающие проекты сутками, будут, наверное, смеяться над такими проблемами.
Ну у всех свои проблемы, а люди, собирающие проекты сутками ИМХО хорошо и уютно устроились на большой зарплате...
Так что я им завидую
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, eremeer, Вы писали:
MM>>Ну а с precompiled headers экспериментировать не пробовал? — все же есть тут что-то совсем мрачное E>precompiled? где-то выше специально упомянул про полный билд а его приходится иногда делать — слетает отладчик в debug-версии проекта, помогает только полный ребилд (говорят, еще может помочь хирург — выправить руки .
Эта, редко же, на ночь можно запускать в конце концов
E>когда сидишь в дебаге — 5 или 10 — разница все-таки есть. (хотя, после посещения хирурга, возможно и не придется корчиться в дебаге...)
А в дебаге ты тоже полный ребилд всё время запускаешь?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Ну здесь уже приведения несвязанных типов. В моем коде все было легально, по крайней мере.
Как я понял проблему, исходный тип P3f из сторонней библиотеки? Если так, то вдвойне плохо.
Нормального решения не знаю. Для сторонних библиотек помогают precompiled headers. Если не менять
заголовки подключаемые в precompiled и не использовать automatic precompiled, то VS у меня не глючит. Решения, базирующиеся на шаблонах, боюсь только замедлит компиляцию.
У меня проект 1 млн. строк компилируется 20 минут. Сокращал время уменьшением связности. Также в библиотеках мелкие классы оставлял как есть, а крупные, сложные и зависимые от сторонних библиотек прятал в pimpl.
Re[5]: Ссылки + forward declaration
От:
Аноним
Дата:
27.09.07 06:03
Оценка:
Здравствуйте, eremeer, Вы писали:
E>структура, наподобие указанной, хранится в здоровенном (около 200кб) заголовочном файле сторонней библиотеки. Мой заголовочный в десятке cpp подключается. В итоге проект на 20 секунд медленнее компилируется (при полной сборке). В проекте сотни три файлов: тут 20 сек, там 30 и получаем вместо 5 минут компиляции, например, 10.
Increadi build спасет отца русской демократии?
Здравствуйте, Erop, Вы писали:
E>// эту функцию реализуешь в ОДНОМ cpp, который собственно и зависит от библиотечного хедера E>extern UsefulDataFromStructFromLib extractUsefulData( const StructFromLib& ); E>ну и в своём классе хранишь константную копию UsefulDataFromStructFromLib без всяких ссылок или указателей
тогда мне еще нужна обратная обертка, чтобы я мог "native" структуру передавать в "native" функции той библиотеки
E>Выход 2 struct StructFromLib; E>Ну и в своём классе хранишь просто поле StructFromLibAccessor.
ну т.е. нет у меня выхода кроме как писать обертки или в виде функций или в виде классов. Не сочти за привереду, но хотелось редких телодвижений
E>>P.S. Люди, собирающие проекты сутками, будут, наверное, смеяться над такими проблемами. E>Ну у всех свои проблемы, а люди, собирающие проекты сутками ИМХО хорошо и уютно устроились на большой зарплате... E>Так что я им завидую
а если это люди, работа которых состоит только в том, чтобы проводить сборки?
Здравствуйте, Erop, Вы писали:
E>А в дебаге ты тоже полный ребилд всё время запускаешь?
Вот тебе смешно, а я сегодня... Сидел, дебажил... а отладчик опять сломался — перепрыгивает через три строчки, будто он в релизе, значения переменных левые показывает (но при этом все правильно работает). Думаю: неужели опять перекомпилять?! Закрыл лицо руками и заплакал. А тут еще тимлидер подошел и грит: еще раз заплачешь — уволю. Так и сказал.
Я писал там выше, что периодически приходится полный ребилд делать из-за проблем с дебаггером. Представляешь, да? Преисполненный торжества от предположения что сел багу на хвост, потираю руки, дрожу от нетерпения, азарт и все такое. А тут бац — жди когда ребилд закончится.
Здравствуйте, AstroMan, Вы писали:
AM>Ну здесь уже приведения несвязанных типов. В моем коде все было легально, по крайней мере. AM>Как я понял проблему, исходный тип P3f из сторонней библиотеки? Если так, то вдвойне плохо. AM>Нормального решения не знаю. Для сторонних библиотек помогают precompiled headers. Если не менять AM>заголовки подключаемые в precompiled и не использовать automatic precompiled, то VS у меня не глючит. Решения, базирующиеся на шаблонах, боюсь только замедлит компиляцию.
Угу, все так. Наверное, придется делать раздельную компиляцию — для релиза полное включение (все равно он медленней дебага компилируется и вопросы скорости там острее) а для дебага какое-нибудь извращение.
Здравствуйте, eremeer, Вы писали:
E>...еще раз заплачешь — уволю. Так и сказал.
Не тем ты чем-то занимаешься, похоже
E>Я писал там выше, что периодически приходится полный ребилд делать из-за проблем с дебаггером. Представляешь, да? Преисполненный торжества от предположения что сел багу на хвост, потираю руки, дрожу от нетерпения, азарт и все такое. А тут бац — жди когда ребилд закончится.
Ну включи библиотеку в pch, она же не меняется?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, eremeer, Вы писали:
E>>Выход 2 struct StructFromLib; E>>Ну и в своём классе хранишь просто поле StructFromLibAccessor. E>ну т.е. нет у меня выхода кроме как писать обертки или в виде функций или в виде классов. Не сочти за привереду, но хотелось редких телодвижений
а разве много телодвиженний?
Можно сделать шаблонную обёртку какую-нибудь кстати, только я бы не стал.
Писать-то в PIMPL'е надо только аксессоры к тем аттрибутам, которые в коде понадобились...
E>>Ну у всех свои проблемы, а люди, собирающие проекты сутками ИМХО хорошо и уютно устроились на большой зарплате... E>>Так что я им завидую E>а если это люди, работа которых состоит только в том, чтобы проводить сборки?
Да какая разница? лишь бы зряплата большая Делать-то пока компилячится ничего не надо
E>using <p3f.h>::P3f;
PCH и все дела
Я вот так и не понял, тебе внутренности P3f нужны?, или ты с ним, как с токеном работаешь?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском