S>Есть ли способ избежать вызова конструктора по умолчанию?
Создавать объекты в массиве символов, выравненном соответствующим образом.
Последнее стандартом (пока) не покрывается. Для одного из возможных вариантов см. boost::aligned_storage или соответствующий пункт документации к библиотеке, поставляющейся с компилятором, если ты являешься счастливым пользователем реализации, уже поддерживающей Technical Report on C++ Library Extensions.
Если от boost по тем или иным причинам зависеть не хочется, то на практике должно быть достаточно поместить массив символов в union вместе с short, int, long, float, double.
template< class T, unsigned N >
class vect;
template< class T >
class vect< T, 3 >
{
private:
union
{
char data[3 * sizeof(T)];
short dummy_short;
int dummy_int;
long dummy_long;
float dummy_float;
double dummy_double;
} u;
public:
inline vect( const T& x, const T& y, const T& z )
{
new(u.data + 0 * sizeof(T)) T(x);
new(u.data + 1 * sizeof(T)) T(y);
new(u.data + 2 * sizeof(T)) T(z);
}
};
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Sabrian, Вы писали:
S>Как известно сабж в С++ отсутствует. S>Еще больше раздражает автоматический вызов конструктора по умолчанию для элементов массива.
S>вот код:
S>
S>template< class T, unsigned N >
S>class vect;
S>template< class T >
S>class vect< T, 3 >
S>{
S>private:
S> T data[3];
S>public:
S> inline vect( const T& x, const T& y, const T& z )
S> {
S> data[0].~T();
S> data[1].~T();
S> data[2].~T();
S> new(data + 0) T(x);
S> new(data + 1) T(y);
S> new(data + 2) T(z);
S> }
S>};
S>
S>Есть ли способ избежать вызова конструктора по умолчанию? S>Заранее благадарен за ответы.
S>Мне нужны быстрые статические вектора, для математических расчетов и.т.п.
Может тогда имеет смысл задуматься о своем, более быстрым чем стандартный, Allocator — е и использовать std::vector?
"В любое мгновение принятия решения, лучшее, что вы можете сделать, это принять правильное решение; следующим лучшим вариантом будет принять неправильное решение, худший вариант – не принимать решения совсем" (c) Теодор Рузвельт.
template <typename _Type, const size_t _Size,
typename _Allocator = std::allocator <_Type> >
class static_vector
{
_Type * const Vector_;
_Allocator Allocator_;
public:
explicit static_vector (const _Type & Value) : Allocator_ (), Vector_ (Allocator_.allocate (_Size))
{
for (size_t i = size_t (); i < _Size; ++ i)
{
Allocator_.construct (Vector_ + i, Value);
}
}
~static_vector ()
{
for (size_t i = size_t (); i < _Size; ++ i)
{
Allocator_.destroy (Vector_ + i);
}
Allocator_.deallocate (Vector_, _Size);
}
};
"В любое мгновение принятия решения, лучшее, что вы можете сделать, это принять правильное решение; следующим лучшим вариантом будет принять неправильное решение, худший вариант – не принимать решения совсем" (c) Теодор Рузвельт.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Создавать объекты в массиве символов, выравненном соответствующим образом.
ПК>Последнее стандартом (пока) не покрывается. Для одного из возможных вариантов см. boost::aligned_storage или соответствующий пункт документации к библиотеке, поставляющейся с компилятором, если ты являешься счастливым пользователем реализации, уже поддерживающей Technical Report on C++ Library Extensions.
ПК>Если от boost по тем или иным причинам зависеть не хочется, то на практике должно быть достаточно поместить массив символов в union вместе с short, int, long, float, double. ПК>
ПК>template< class T, unsigned N >
ПК>class vect;
ПК>template< class T >
ПК>class vect< T, 3 >
ПК>{
ПК>private:
ПК> union
ПК> {
ПК> char data[3 * sizeof(T)];
ПК> short dummy_short;
ПК> int dummy_int;
ПК> long dummy_long;
ПК> float dummy_float;
ПК> double dummy_double;
ПК> } u;
ПК>public:
ПК> inline vect( const T& x, const T& y, const T& z )
ПК> {
ПК> new(u.data + 0 * sizeof(T)) T(x);
ПК> new(u.data + 1 * sizeof(T)) T(y);
ПК> new(u.data + 2 * sizeof(T)) T(z);
ПК> }
ПК>};
ПК>
а почему в union надо еще класть short, int, long, float и double?
Здравствуйте, bolshik, Вы писали:
B>Здравствуйте, Павел Кузнецов, Вы писали:
ПК>>Создавать объекты в массиве символов, выравненном соответствующим образом.
ПК>>Последнее стандартом (пока) не покрывается. Для одного из возможных вариантов см. boost::aligned_storage или соответствующий пункт документации к библиотеке, поставляющейся с компилятором, если ты являешься счастливым пользователем реализации, уже поддерживающей Technical Report on C++ Library Extensions.
ПК>>Если от boost по тем или иным причинам зависеть не хочется, то на практике должно быть достаточно поместить массив символов в union вместе с short, int, long, float, double. ПК>>
ПК>>template< class T, unsigned N >
ПК>>class vect;
ПК>>template< class T >
ПК>>class vect< T, 3 >
ПК>>{
ПК>>private:
ПК>> union
ПК>> {
ПК>> char data[3 * sizeof(T)];
ПК>> short dummy_short;
ПК>> int dummy_int;
ПК>> long dummy_long;
ПК>> float dummy_float;
ПК>> double dummy_double;
ПК>> } u;
ПК>>public:
ПК>> inline vect( const T& x, const T& y, const T& z )
ПК>> {
ПК>> new(u.data + 0 * sizeof(T)) T(x);
ПК>> new(u.data + 1 * sizeof(T)) T(y);
ПК>> new(u.data + 2 * sizeof(T)) T(z);
ПК>> }
ПК>>};
ПК>>
B> а почему в union надо еще класть short, int, long, float и double?
Потому что все элементы union а должны располагаться по одному адресу -- адресу этого union а. Это требование стандарта.
Таким образом, компилятор вынужден выровнять начало под типы short,int,long,float,double, чего практически достаточно.
Для полноты лучше ещё добавить типы void *,void (*)(),UnknownClass *,UnknownClass UnknownClass::*,UnknownClass (UnknownClass::*)();
Здравствуйте, Шахтер, Вы писали:
Ш>Потому что все элементы union а должны располагаться по одному адресу -- адресу этого union а. Это требование стандарта. Ш>Таким образом, компилятор вынужден выровнять начало под типы short,int,long,float,double, чего практически достаточно. Ш>Для полноты лучше ещё добавить типы void *,void (*)(),UnknownClass *,UnknownClass UnknownClass::*,UnknownClass (UnknownClass::*)();
а что значит
вынужден выровнять начало
?
Т.е. непонятно, в чем разница м\д union above и таким
N>Может тогда имеет смысл задуматься о своем, более быстрым чем стандартный, Allocator — е и использовать std::vector?
Ну какая аллокация для 3-4 float/double? Это все равно медленно. Мне итератором по ним не бегать, мне нужны методы такие как length, normalize и.т.д. Т.е математический вектор это не контейнер, и предназнаен для дркгих целей.
Здравствуйте, Павел Кузнецов, Вы писали:
N>Создавать объекты в массиве символов, выравненном соответствующим образом. N>Последнее стандартом (пока) не покрывается. Для одного из возможных вариантов см. boost::aligned_storage
Да, спасибо. Обязательно посмотрю. Кстати ведь компилятор применит соглашения о выравниваниях и к переменной u, следовательно данные должны оказаться выравнены? Кроме того тут:
можно масштабировать не на sizeof(T), а например на его округление до 4 -> можно вручную выровнять элементы. необходимо только, чтобы u лежал по выровненному адресу.
Здравствуйте, bolshik, Вы писали:
B>Здравствуйте, Шахтер, Вы писали:
Ш>>Потому что все элементы union а должны располагаться по одному адресу -- адресу этого union а. Это требование стандарта. Ш>>Таким образом, компилятор вынужден выровнять начало под типы short,int,long,float,double, чего практически достаточно. Ш>>Для полноты лучше ещё добавить типы void *,void (*)(),UnknownClass *,UnknownClass UnknownClass::*,UnknownClass (UnknownClass::*)();
B> а что значит B>
B>вынужден выровнять начало
B>?
B>Т.е. непонятно, в чем разница м\д union above и таким B>
B>union {
B> char data[3 * sizeof(T)];
B>} u;
B>
Допустим, архитектура компьютера позволяет иметь char по любому адресу, а к примеру, int должен быть выровнян по 4 байтам (то есть его адрес должен делится на 4). Тогда делая reinterpret_cast<int*>(u.data) и разыменовывая этот указатель -- мы получим аппаратное исключение. Обычная реакция оси на такие исключния -- убийство процесса..
Здравствуйте, BitField, Вы писали:
BF>Допустим, архитектура компьютера позволяет иметь char по любому адресу, а к примеру, int должен быть выровнян по 4 байтам (то есть его адрес должен делится на 4). Тогда делая reinterpret_cast<int*>(u.data) и разыменовывая этот указатель -- мы получим аппаратное исключение. Обычная реакция оси на такие исключния -- убийство процесса..
Hello, !
You wrote on Wed, 01 Feb 2006 03:38:09 GMT:
ПК> Если от boost по тем или иным причинам зависеть не хочется, то на ПК> практике должно быть достаточно поместить массив символов в union ПК> вместе с short, int, long, float, double.
А есть ли гарантия (в стандарте), что в этом случае начало данных data будут выровнено так, чтобы в них можно было поместить объект? Или это применимо только для некоторых компиляторов?
Здравствуйте, ArtDenis, Вы писали:
ПК>> Если от boost по тем или иным причинам зависеть не хочется, то на ПК>> практике должно быть достаточно поместить массив символов в union ПК>> вместе с short, int, long, float, double.
AD>А есть ли гарантия (в стандарте), что в этом случае начало данных data будут выровнено так, чтобы в них можно было поместить объект? Или это применимо только для некоторых компиляторов?
Есть гарантия, что туда можно будет поместить любой объект, требования выравнивания которого не строже, чем требования для short, int, long, float, double. Это вытекает из того, что для POD-объединений, каковым является объединение, описанное выше, стандарт гарантирует, что все их члены располагаются по общему адресу. Точнее, говорится, что каждый член объединения располагается так же, как если бы он был единственным членом структуры, а уже для POD-структур говорится, что указатель на их начало совпадает с указателем на их первый член; структура, содержащая единственный член любого из перечисленных выше типов является POD-структурой.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, MaximE, Вы писали: ME>Тут говорят про 3-4 float/double. У массивов с такими элементами их конструкторы не вызываются по-умолчанию.
1) Зависит от реализации
2) А для пользовательских скалярных типов? И для смарт-поинтеров и хендлов...
Ну, ладно... сегодня в boost покапаюсь, посмотрю что за зверь такой aligned_storage и как оно работает...
On Wed, 01 Feb 2006 16:12:55 -0000, Sabrian <50840@users.rsdn.ru> wrote:
> Здравствуйте, MaximE, Вы писали: > ME>Тут говорят про 3-4 float/double. У массивов с такими элементами их конструкторы не вызываются по-умолчанию. > 1) Зависит от реализации
Не зависит. Встроенные типы имеют псеводо-конструктор, который можно вызвать только явно. Если ты не инициализирушь
> 2) А для пользовательских скалярных типов? И для смарт-поинтеров и хендлов...
Для не POD-типов будет вызван дефолтный конструктор.
Про смарт-поинтеры и хэндлы — как над ними производить математические расчеты?
BF>Допустим, архитектура компьютера позволяет иметь char по любому адресу, а к примеру, int должен быть выровнян по 4 байтам (то есть его адрес должен делится на 4). Тогда делая reinterpret_cast<int*>(u.data) и разыменовывая этот указатель -- мы получим аппаратное исключение. Обычная реакция оси на такие исключния -- убийство процесса..
Всё бы ничего, но разве вот sizeof не обязан быть кратен выравниванию типа?
Вроде как такие вот фокусы совершенно portable должны быть:
class T .... {
...
T& GetNextInVector() { return this[1]; }
....
};
или я что-то пропустил?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском