2013-05-09 1 views
3

나는 매개 변수 형식의 스택 할당 된 배열이 필요한 제네릭 형식에서 작업하고 있습니다. 가능한 한 적은 오버 헤드를 가진 것으로되어 있습니다. 시험의 일부 였지만 지금은 호기심을 불러 일으켰습니다. 나는 주변을 둘러 보려고 노력하지만 유용한 것을 찾지 못했습니다.C++에서 매개 변수화 된 형식의 배열 초기화

배열을 만들고 멤버를 초기화하려고하는데 올바르게 수행하는 방법이 확실하지 않습니다. 나는 다음과 같은 코드를 가지고있다 :

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

이제 T는 기본 생성자 인 표준 산술 연산자를 갖는 모든 것이 될 수있다. 이러한 복식 같은 유형의 잘 작동

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

: T는 이중 때 은 내가 가진 배열을 초기화. 이제 문제는 T가 될 수 있다는 것입니다 같은 합리적인 같은 : 모든 것이 0 또 다른 방법으로 설정 한 후 우리는 더블로 변환하는 경우 문제가 발생할 수

접근 한

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

접근법 2

for(size_t i = 0; i < _dim; i++) 
{ 
    b[i] = T(); 
} 
: 저점이 같은 모든 요소를 ​​실행하는 것입니다 0

구성원을 올바르게 초기화하는 효과적인 방법은 무엇입니까?

사이드 노드는 합리적인 것보다 다른 유형을 사용하지 않는 경우입니다. 예를 들어 더블. 이 프로그램은 잘 실행하지만, (반복, 그들 중 많은) 다음과 같은 오류 메시지와 함께 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의 불평을 중지 만들어 내 두 가지 방법 중 하나를 수행.

업데이트 변수 _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)); 
} 
+2

나는이 질문을 정말로 이해하지 못한다. 배열 요소는 배열을 정의 할 때 기본 초기화됩니다. –

+0

@sftrabbit :하지만 클래스가 아닌 유형의 경우 초기화가 필요하지 않습니까? 아닙니다. –

+0

@AndyProwl 그래, 어쩌면 나는 그 질문을 오해하고있다. : D 조 편집 : 아, 이제 알 겠어. –

답변

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]; 
} 

출력은 다음과 같습니다 그래서 당신은 클래스 유형해야 할 특별한 아무것도

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

없다. 그러나 내장 유형의 경우 기본 ctor가 없으므로 각 요소를 초기화하는 값으로 두 개의 중괄호 (예 : T b[_dim] = {};)를 추가해야합니다. 이렇게하면 클래스 유형 및 내장 유형에서 작동합니다.

+0

나는 OP가 배열이 모든 시간에 초기화되기를 원한다고 생각한다. 즉, 클래스 타입을 포함 할 때 기본 생성을 의미하고, 스칼라 타입을 포함 할 때 값을 초기화한다는 의미이다. "나는 필요한 일반 타입을 사용하고있다. 매개 변수 유형의 스택 할당 배열. " 비록 내가 모든 것을 오해하지 않았다면 확실하지 않다. –

+0

@AndyProwl : 그래, 아마 맞을거야. 나는 OP에 오해가 있다고 생각하고 그것을 지적하고 싶었다. –

1

당신은 다른 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]); 
} 
관련 문제