C ++의 클래스 이니셜 라이저에서 const 배열 초기화
C ++에 다음 클래스가 있습니다.
class a {
const int b[2];
// other stuff follows
// and here's the constructor
a(void);
}
질문은 b가 생성자 함수의 본문 내부에서 초기화 할 수없는 경우 초기화 목록에서 b를 어떻게 초기화 const
합니까?
작동하지 않습니다.
a::a(void) :
b([2,3])
{
// other initialization stuff
}
편집 : 중요한 경우는 b
인스턴스 마다 다른 값을 가질 수 있지만 값은 인스턴스 수명 동안 일정하다고 알려져 있습니다.
다른 사람들이 말했듯이 ISO C ++는이를 지원하지 않습니다. 그러나이를 해결할 수 있습니다. 대신 std :: vector를 사용하십시오.
int* a = new int[N];
// fill a
class C {
const std::vector<int> v;
public:
C():v(a, a+N) {}
};
C ++ 11에서는이 질문에 대한 답이 변경되었으며 실제로 다음과 같이 할 수 있습니다.
struct a {
const int b[2];
// other bits follow
// and here's the constructor
a();
};
a::a() :
b{2,3}
{
// other constructor work
}
int main() {
a a;
}
현재 표준에서는 불가능합니다. 이니셜 라이저 목록을 사용하여 C ++ 0x에서이 작업을 수행 할 수있을 것이라고 믿습니다 ( 초기화 목록 및 기타 멋진 C ++ 0x 기능에 대한 자세한 내용은 Bjarne Stroustrup의 A Brief Look at C ++ 0x 참조).
std::vector
힙을 사용합니다. 이런, const
온전한 검사를 위해 얼마나 낭비가 될까요. 요점은 std::vector
컴파일 타임에 수행해야하는 이전 구문 검사가 아니라 런타임에 동적 성장입니다. 성장하지 않으려면 일반 배열을 래핑하는 클래스를 만듭니다.
#include <stdio.h>
template <class Type, size_t MaxLength>
class ConstFixedSizeArrayFiller {
private:
size_t length;
public:
ConstFixedSizeArrayFiller() : length(0) {
}
virtual ~ConstFixedSizeArrayFiller() {
}
virtual void Fill(Type *array) = 0;
protected:
void add_element(Type *array, const Type & element)
{
if(length >= MaxLength) {
// todo: throw more appropriate out-of-bounds exception
throw 0;
}
array[length] = element;
length++;
}
};
template <class Type, size_t Length>
class ConstFixedSizeArray {
private:
Type array[Length];
public:
explicit ConstFixedSizeArray(
ConstFixedSizeArrayFiller<Type, Length> & filler
) {
filler.Fill(array);
}
const Type *Array() const {
return array;
}
size_t ArrayLength() const {
return Length;
}
};
class a {
private:
class b_filler : public ConstFixedSizeArrayFiller<int, 2> {
public:
virtual ~b_filler() {
}
virtual void Fill(int *array) {
add_element(array, 87);
add_element(array, 96);
}
};
const ConstFixedSizeArray<int, 2> b;
public:
a(void) : b(b_filler()) {
}
void print_items() {
size_t i;
for(i = 0; i < b.ArrayLength(); i++)
{
printf("%d\n", b.Array()[i]);
}
}
};
int main()
{
a x;
x.print_items();
return 0;
}
ConstFixedSizeArrayFiller
및 ConstFixedSizeArray
재사용.
첫 번째는 배열을 초기화하는 동안 (벡터와 동일) 런타임 경계 검사를 허용하며, 이는 나중에이 const
초기화 후에 발생할 수 있습니다 .
두 번째는 배열을 다른 객체 내부에 할당 할 수 있도록합니다. 다른 객체는 힙에 있거나 객체가있는 경우 단순히 스택에있을 수 있습니다. 힙에서 할당하는 시간 낭비가 없습니다. 또한 배열에 대한 컴파일 타임 const 검사를 수행합니다.
b_filler
초기화 값을 제공하는 작은 개인 클래스입니다. 배열의 크기는 템플릿 인수를 사용하여 컴파일 타임에 확인되므로 범위를 벗어날 가능성이 없습니다.
나는 이것을 수정하는 더 이국적인 방법이 있다고 확신합니다. 이것은 초기 찌르기입니다. 클래스에 대한 컴파일러의 단점을 거의 보완 할 수 있다고 생각합니다.
ISO 표준 C ++에서는이를 수행 할 수 없습니다. 그렇다면 구문은 다음과 같습니다.
a::a(void) :
b({2,3})
{
// other initialization stuff
}
아니면 그 라인을 따라 뭔가. 귀하의 질문에 따르면 실제로 원하는 것은 배열 인 상수 클래스 (정적) 멤버 인 것처럼 들립니다. C ++는 이것을 가능하게합니다. 이렇게 :
#include <iostream>
class A
{
public:
A();
static const int a[2];
};
const int A::a[2] = {0, 1};
A::A()
{
}
int main (int argc, char * const argv[])
{
std::cout << "A::a => " << A::a[0] << ", " << A::a[1] << "\n";
return 0;
}
출력은 다음과 같습니다.
A::a => 0, 1
물론 이것은 정적 클래스 멤버이기 때문에 클래스 A의 모든 인스턴스에 대해 동일합니다. 이것이 원하는 것이 아닌 경우, 즉 A의 각 인스턴스가 배열 a에서 다른 요소 값을 갖기를 원합니다. 배열을 const로 시작하려는 실수. 다음과 같이해야합니다.
#include <iostream>
class A
{
public:
A();
int a[2];
};
A::A()
{
a[0] = 9; // or some calculation
a[1] = 10; // or some calculation
}
int main (int argc, char * const argv[])
{
A v;
std::cout << "v.a => " << v.a[0] << ", " << v.a[1] << "\n";
return 0;
}
내가 상수 배열이있는 곳에서는 항상 정적으로 수행되었습니다. 수락 할 수 있다면이 코드가 컴파일되고 실행되어야합니다.
#include <stdio.h>
#include <stdlib.h>
class a {
static const int b[2];
public:
a(void) {
for(int i = 0; i < 2; i++) {
printf("b[%d] = [%d]\n", i, b[i]);
}
}
};
const int a::b[2] = { 4, 2 };
int main(int argc, char **argv)
{
a foo;
return 0;
}
초기화 목록에서는 할 수 없습니다.
이것 좀보세요 :
http://www.cprogramming.com/tutorial/initialization-lists-c++.html
:)
A solution without using the heap with std::vector
is to use boost::array
, though you can't initialize array members directly in the constructor.
#include <boost/array.hpp>
const boost::array<int, 2> aa={ { 2, 3} };
class A {
const boost::array<int, 2> b;
A():b(aa){};
};
How about emulating a const array via an accessor function? It's non-static (as you requested), and it doesn't require stl or any other library:
class a {
int privateB[2];
public:
a(int b0,b1) { privateB[0]=b0; privateB[1]=b1; }
int b(const int idx) { return privateB[idx]; }
}
Because a::privateB is private, it is effectively constant outside a::, and you can access it similar to an array, e.g.
a aobj(2,3); // initialize "constant array" b[]
n = aobj.b(1); // read b[1] (write impossible from here)
If you are willing to use a pair of classes, you could additionally protect privateB from member functions. This could be done by inheriting a; but I think I prefer John Harrison's comp.lang.c++ post using a const class.
interestingly, in C# you have the keyword const that translates to C++'s static const, as opposed to readonly which can be only set at constructors and initializations, even by non-constants, ex:
readonly DateTime a = DateTime.Now;
I agree, if you have a const pre-defined array you might as well make it static. At that point you can use this interesting syntax:
//in header file
class a{
static const int SIZE;
static const char array[][10];
};
//in cpp file:
const int a::SIZE = 5;
const char array[SIZE][10] = {"hello", "cruel","world","goodbye", "!"};
however, I did not find a way around the constant '10'. The reason is clear though, it needs it to know how to perform accessing to the array. A possible alternative is to use #define, but I dislike that method and I #undef at the end of the header, with a comment to edit there at CPP as well in case if a change.
참고URL : https://stackoverflow.com/questions/161790/initialize-a-const-array-in-a-class-initializer-in-c
'program tip' 카테고리의 다른 글
키 값 쌍 데이터 구조를위한 최상의 구현? (0) | 2020.10.26 |
---|---|
현대 시대의 포트란 배우기 (0) | 2020.10.26 |
Facebook 좋아요 버튼-수 숨기기? (0) | 2020.10.26 |
$ location을 사용하여 AngularJS의 새 페이지로 리디렉션 (0) | 2020.10.26 |
.css 파일 (flask / python)을 선택하지 않는 애플리케이션 (0) | 2020.10.26 |