在c++中初始化参数化类型数组
Initializing array of parameterized type in c++
我正在研究一种泛型类型,其中我需要一个参数类型的堆栈分配数组。它应该有尽可能少的开销。这是考试的一部分,但现在它激起了我的好奇心。我试着到处找,但没找到任何有用的东西。
我试图创建一个数组并初始化成员,但我不完全确定如何正确地做到这一点。我有以下代码:
T b[_dim]; // typeof(_dim) == size_t
现在T可以是任何具有标准算术运算符的东西,一个默认构造函数。当T是双精度类型时,用
初始化数组memset(b, 0, _dim*sizeof(T));
对于double类型可以正常工作。现在的问题是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();
}
正确初始化成员的有效方法是什么?
边节点是当我对除有理数以外的其他类型都不这样做时的节点。比如双精度。程序运行正常,但是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<double>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, char, double) 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, double) const (locale_facets.tcc:1144)
==24450== by 0x53A5966: std::ostream& std::ostream::_M_insert<double>(double) (locale_facets.h:2398)
==24450== by 0x433E9D: void boost::io::detail::put_last<char, std::char_traits<char>, double>(std::basic_ostream<char, std::char_traits<char> >&, double&) (feed_args.hpp:115)
==24450== by 0x43273E: void boost::io::detail::put<char, std::char_traits<char>, std::allocator<char>, double&>(double&, 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>, double&>(boost::basic_format<char, std::char_traits<char>, std::allocator<char> >&, double&) (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>, double&>(boost::basic_format<char, std::char_traits<char>, std::allocator<char> >&, double&) (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%<double>(double&) (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<double>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, char, double) 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, double) const (locale_facets.tcc:1144)
==24450== by 0x53A5966: std::ostream& std::ostream::_M_insert<double>(double) (locale_facets.h:2398)
==24450== by 0x433E9D: void boost::io::detail::put_last<char, std::char_traits<char>, double>(std::basic_ostream<char, std::char_traits<char> >&, double&) (feed_args.hpp:115)
==24450== by 0x43273E: void boost::io::detail::put<char, std::char_traits<char>, std::allocator<char>, double&>(double&, 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>, double&>(boost::basic_format<char, std::char_traits<char>, std::allocator<char> >&, double&) (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>, double&>(boost::basic_format<char, std::char_traits<char>, std::allocator<char> >&, double&) (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%<double>(double&) (format_class.hpp:68)
我的两种方法中的任何一种都让valgrind停止了抱怨。Update变量_dim确实是变量,并被解析为。g++ 11说:
error: variable-sized object ‘b’ may not be initialized
解决方案及总结如上所述,这将调用所有元素的元素:
b T[_dim];
由于_dim是变量,这不起作用:
b T[_dim] = {};
但是我们可以用do this::
T b[_dim];
if(std::is_fundamental<T>::value)
{
memset(b, 0, _dim*sizeof(T));
}
正如strabbit已经指出的那样,在定义数组时将为您调用默认的actor。对于以下代码:
#include <iostream>
struct Rational
{
int numerator;
int denominator;
Rational(): numerator(0), denominator(1)
{std::cout << "Rational ctor!" << std::endl;}
};
int main()
{
Rational arr[10];
}
输出为:
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,我假设您正在使用的c++支持覆盖。
void init(double& t)
{
t = 0;
}
void init(Rational& t)
{
t.numerator = 0;
t.denominator= 0;
}
然后:
for(size_t i = 0; i < _dim; i++)
{
inti(b[i]);
}
相关文章:
- 如何使用Visual Studio 2017在C++中为参数化对象数组使用唯一指针
- 如何使用非类型模板参数传入指向数组的指针
- 使用带有参数包的数组的成员数组初始化类
- 从非类型模板参数声明 constexpr 数组的可移植方法
- 给定类型的模板化中间数组
- 使用从1到N的数字初始化std数组模板参数
- 在可变参数构造函数中初始化常量数组
- 构造函数不会将使用 new 初始化的数组作为参数
- 使用作为参数传递的 std::intializer_list 初始化 std::数组
- 复杂类型数组的静态初始化
- 如何将初始值设定项与右值引用参数一起使用 // 为什么不能使用另一个 C 样式数组变量初始化 C 样式数组
- 仅当数组属于特定类型时,才将模板化参数添加到数组
- 如何在C++中初始化需要参数的结构数组
- 节点C++插件 - 当类型数组(Float32Array)作为参数传递时,如何访问它?
- 使用构造函数参数初始化结构数组
- 使用构造函数初始化对象数组,该构造函数接受用于创建对象的参数
- 如何将抽象类型数组作为函数参数传递
- 如何使用运行参数从模板实例化对象数组
- 如何初始化构造函数需要两个或多个参数的对象数组
- 在c++中初始化参数化类型数组