В 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 спасет отца русской демократии?