Инициализация массива параметризованного типа в С++

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

Я пытаюсь создать массив и инициализировать члены, но я не совсем уверен, как это сделать правильно. У меня есть следующий код:

T b[_dim]; // typeof(_dim) == size_t

Теперь T может быть любым, у которого есть стандартные арифметические операторы, конструктор по умолчанию. Когда T был двойным, я инициализировал массив с помощью:

memset(b, 0, _dim*sizeof(T));

Что отлично подходит для таких типов, как парные. Теперь проблема в том, что T может быть рациональным, например:

Подход 1

struct Rational
{
 int numerator; 
 int denominator;
 Rational(): numerator(0), denominator(1) {}
};

Это может вызвать проблемы, если мы преобразуем его в ****** после того, как все установлено на 0. Другой подход заключается в том, чтобы выполнить все элементы, подобные этому:

Подход 2

for(size_t i = 0; i < _dim; i++)
{
 b[i] = T();
}

Каков эффективный способ инициализации членов правильно?

Сторона node заключается в том, что когда я не делаю ни одного другого типа, кроме рационального. Например, двойной. Программа работает нормально, но valgrind жалуется на следующие сообщения об ошибках (много их, несколько раз):

==24450== Conditional jump or move depends on uninitialised value(s)
==24450== at 0x5878B60: __printf_fp (printf_fp.c:731)
==24450== by 0x5876B4B: vfprintf (vfprintf.c:1654)
==24450== by 0x589B654: vsnprintf (vsnprintf.c:119)
==24450== by 0x53938FD: std::__convert_from_v(__locale_struct* const&, char*, int, char const*, ...) (c++locale.h:93)
==24450== by 0x53A118C: std::ostreambuf_iterator<char, std::char_traits<char=""> > std::num_put<char, std::ostreambuf_iterator<char,="" std::char_traits<char=""> > >::_M_insert_float<******>(std::ostreambuf_iterator<char, std::char_traits<char=""> >, std::ios_base&, char, char, ******) const (locale_facets.tcc:997)
==24450== by 0x53A141F: std::num_put<char, std::ostreambuf_iterator<char,="" std::char_traits<char=""> > >::do_put(std::ostreambuf_iterator<char, std::char_traits<char=""> >, std::ios_base&, char, ******) const (locale_facets.tcc:1144)
==24450== by 0x53A5966: std::ostream& std::ostream::_M_insert<******>(******) (locale_facets.h:2398)
==24450== by 0x433E9D: void boost::io::detail::put_last<char, std::char_traits<char="">, ******>(std::basic_ostream<char, std::char_traits<char=""> >&, ******&) (feed_args.hpp:115)
==24450== by 0x43273E: void boost::io::detail::put<char, std::char_traits<char="">, std::allocator<char>, ******&>(******&, boost::io::detail::format_item<char, std::char_traits<char="">, std::allocator<char> > const&, boost::basic_format<char, std::char_traits<char="">, std::allocator<char> >::string_type&, boost::basic_format<char, std::char_traits<char="">, std::allocator<char> >::internal_streambuf_t&, std::locale*) (feed_args.hpp:176)
==24450== by 0x43141F: void boost::io::detail::distribute<char, std::char_traits<char="">, std::allocator<char>, ******&>(boost::basic_format<char, std::char_traits<char="">, std::allocator<char> >&, ******&) (feed_args.hpp:253)
==24450== by 0x42F22F: boost::basic_format<char, std::char_traits<char="">, std::allocator<char> >& boost::io::detail::feed<char, std::char_traits<char="">, std::allocator<char>, ******&>(boost::basic_format<char, std::char_traits<char="">, std::allocator<char> >&, ******&) (feed_args.hpp:263)
==24450== by 0x42DB1E: boost::basic_format<char, std::char_traits<char="">, std::allocator<char> >& boost::basic_format<char, std::char_traits<char="">, std::allocator<char> >::operator%<******>(******&) (format_class.hpp:68)
==24450== 
==24450== Use of uninitialised value of size 8
==24450== at 0x5878B6A: __printf_fp (printf_fp.c:731)
==24450== by 0x5876B4B: vfprintf (vfprintf.c:1654)
==24450== by 0x589B654: vsnprintf (vsnprintf.c:119)
==24450== by 0x53938FD: std::__convert_from_v(__locale_struct* const&, char*, int, char const*, ...) (c++locale.h:93)
==24450== by 0x53A118C: std::ostreambuf_iterator<char, std::char_traits<char=""> > std::num_put<char, std::ostreambuf_iterator<char,="" std::char_traits<char=""> > >::_M_insert_float<******>(std::ostreambuf_iterator<char, std::char_traits<char=""> >, std::ios_base&, char, char, ******) const (locale_facets.tcc:997)
==24450== by 0x53A141F: std::num_put<char, std::ostreambuf_iterator<char,="" std::char_traits<char=""> > >::do_put(std::ostreambuf_iterator<char, std::char_traits<char=""> >, std::ios_base&, char, ******) const (locale_facets.tcc:1144)
==24450== by 0x53A5966: std::ostream& std::ostream::_M_insert<******>(******) (locale_facets.h:2398)
==24450== by 0x433E9D: void boost::io::detail::put_last<char, std::char_traits<char="">, ******>(std::basic_ostream<char, std::char_traits<char=""> >&, ******&) (feed_args.hpp:115)
==24450== by 0x43273E: void boost::io::detail::put<char, std::char_traits<char="">, std::allocator<char>, ******&>(******&, boost::io::detail::format_item<char, std::char_traits<char="">, std::allocator<char> > const&, boost::basic_format<char, std::char_traits<char="">, std::allocator<char> >::string_type&, boost::basic_format<char, std::char_traits<char="">, std::allocator<char> >::internal_streambuf_t&, std::locale*) (feed_args.hpp:176)
==24450== by 0x43141F: void boost::io::detail::distribute<char, std::char_traits<char="">, std::allocator<char>, ******&>(boost::basic_format<char, std::char_traits<char="">, std::allocator<char> >&, ******&) (feed_args.hpp:253)
==24450== by 0x42F22F: boost::basic_format<char, std::char_traits<char="">, std::allocator<char> >& boost::io::detail::feed<char, std::char_traits<char="">, std::allocator<char>, ******&>(boost::basic_format<char, std::char_traits<char="">, std::allocator<char> >&, ******&) (feed_args.hpp:263)
==24450== by 0x42DB1E: boost::basic_format<char, std::char_traits<char="">, std::allocator<char> >& boost::basic_format<char, std::char_traits<char="">, std::allocator<char> >::operator%<******>(******&) (format_class.hpp:68)
</******></char></char,></char></char,></char></char,></char></char,></char></char,></char></char,></char></char,></char></char,></char></char,></char></char,></char></char,></char,></char,></******></char,></char,></char,></******></char,></char,></******></char></char,></char></char,></char></char,></char></char,></char></char,></char></char,></char></char,></char></char,></char></char,></char></char,></char></char,></char,></char,></******></char,></char,></char,></******></char,></char,>

Выполнение одного из моих двух подходов заставил valgrind перестать жаловаться.

Обновить переменная _dim действительно является переменной и анализируется. g++ 11 говорит:

error: variable-sized object ‘b’ may not be initialized

Решение и сводка Как указывалось, это вызов ctor для всех элементов:

b T[_dim];

И поскольку переменная _dim является переменной, это не работает:

b T[_dim] = {};

Но мы можем использовать это:

T b[_dim];
if(std::is_fundamental<t>::value)
{
 memset(b, 0, _dim*sizeof(T));
}
</t>
2 ответа

Как stfrabbit уже указывает, по умолчанию ctor будет вызван для вас, когда вы определите массив. Для следующего кода:

#include <iostream>
struct Rational
{
 int numerator; 
 int denominator;
 Rational(): numerator(0), denominator(1)
 {std::cout << "Rational ctor!" << std::endl;}
};
int main()
{
 Rational arr[10];
}
</iostream>

Вывод:

Rational ctor!
Rational ctor!
Rational ctor!
Rational ctor!
Rational ctor!
Rational ctor!
Rational ctor!
Rational ctor!
Rational ctor!
Rational ctor!

Таким образом, для типов классов нет ничего особенного. Однако для встроенных типов не существует значения по умолчанию ctor, поэтому вам нужно добавить пару фигурных скобок, т.е. T b[_dim] = {};, чтобы значение инициализировало каждый элемент. Делая это, он будет работать с типами классов и встроенными типами.


Вы можете определить функции переопределения для инициализации для разных T, я предполагаю, что С++ вы используете переопределение поддержки.

void init(******& t)
{
 t = 0;
}
void init(Rational& t)
{
 t.numerator = 0;
 t.denominator= 0;
}

а затем:

for(size_t i = 0; i < _dim; i++)
{
 inti(b[i]);
}

licensed under cc by-sa 3.0 with attribution.