int/double/등의 생성자 의미 체계입니다. 다음과 같습니다 :기본 형식의 생성자 의미를 모방 한 C++ 형식을 만들 수 있습니까?
정확하게 동일한 동작으로 클래스를 정의 할 수 있습니까? 즉, 기본 생성자를 초기화하지 않고 초기화한 모두가있는 것입니까? 저는 이것이 불가능하다고 믿습니다. 그리고 현재는 0으로 호출 될 때만 컴파일되는 생성자를 만들지 만 근본적인 형식을 정확히 모방 할 방법이 없는지 확인하고자합니다.
int/double/등의 생성자 의미 체계입니다. 다음과 같습니다 :기본 형식의 생성자 의미를 모방 한 C++ 형식을 만들 수 있습니까?
정확하게 동일한 동작으로 클래스를 정의 할 수 있습니까? 즉, 기본 생성자를 초기화하지 않고 초기화한 모두가있는 것입니까? 저는 이것이 불가능하다고 믿습니다. 그리고 현재는 0으로 호출 될 때만 컴파일되는 생성자를 만들지 만 근본적인 형식을 정확히 모방 할 방법이 없는지 확인하고자합니다.
가 더 생성자가 정의되지 않은 경우 :
struct A { int x; };
A a; // default-initialized (unintialized)
A b = A(); // value-initialized
A c = { 4 }; // four
네, @ Jerry의 코멘트를보십시오. 그러나 "고전적인"OOD 클래스는 아닙니다. – littleadv
흠. 나는 이것이 효과가 없다고 믿었지만, valgrind는 나에게 어떤 식 으로든 말하지 않는다. 내가 아는 한, A()는 아직 초기화되지 않았습니다. –
이것이 실제로 작동하면 나는 알고 싶어한다. 다른 사람이 이것이 올바른지 알고 있습니까?내 작은 테스트 프로그램은 "초기화 된"및 "값 초기화 된"두 가지 경우 모두에 0을 인쇄하지만 두 경우 모두 0이 우연이라고 생각합니다. Valgrind는 문제의 메모리가 스택 재사용이기 때문에 아마도 아무 것도 말하지 않습니다. –
기본 제공 유형과 반대로 클래스 생성자가 이 항상이되므로 불가능합니다.
"초기화되지 않은"개체를 정말로 만들고 싶다면 (왜 초기화되지 않은 변수로 인해 버그가 충분하지 않습니까?) 배치 new
으로 트릭을해야합니다.
얼마나 자주 stackoverflow 사람들은 완벽하게 합리적인 질문 충격을받습니다. C++의 디자인 원칙 중 하나는 사용자 정의 유형이 내장 유형에 가능한 한 동일해야하며 이는 언어의 한 가지 구멍입니다. 또한 관련 코드에서 초기화되지 않은 변수에 의해 발생하는 유일한 오류는 valgrind 덕분에 초기화가 0 인 경우를 찾기가 훨씬 어려웠습니다. –
@Geoffrey : "* C++의 디자인 원칙 중 하나는 사용자 정의 유형이 내장 유형에 가능한 한 동일해야한다는 것입니다. *"아니요. 기본 유형과 스칼라는 모두 특별한 의미를 지니고 있습니다. C++ 표준, 특히 _ 초기화와 관련됩니다. – ildjarn
@GeoffreyIrving하지만 C++의 또 다른 원칙은 기본적인 기본 제공 유형이 ** 클래스가 아닌 ** 클래스라는 것입니다. 무언가를 'int'로 'typedef'한다면, 그것은'int'와 똑같이 행동 할 것입니다. 왜 비 클래스 유형과 클래스 유형이 동일하게 동작 할 것이라고 기대합니까? 그리고 나는 그것에 대해 전혀 즐겁지 않습니다. – littleadv
class A {
public:
A() {}
};
A* a = (A*)malloc(sizeof(A));
(.! 아이들을 집에서이 작업을 수행하지 않는 모든이 작업을 수행하지 마십시오)
"초기화되지 않은 건설은"모순 어법이다.
초기화의 부족은 버그 (전체 개체를 재귀 적으로 생성하지 못함)의 결과로 발생합니다.
C++ 클래스에 생성자가 있으면 호출됩니다. 어떤 이유로 든 호출 할 수없는 경우 해당 상황은 잘못된 것입니다 (예를 들어 생성자와 일치하지 않는 잘못된 생성자 인수가 전달 된 경우).
C++ 클래스에는 기본 유형의 멤버가 포함될 수 있으며 생성자는 해당 멤버를 초기화하지 않을 수 있습니다.
이것은 최적화를 위해 악용 될 수 있습니다. 나중에 발생하는 복잡한 초기화가있는 경우 해당 멤버에 쓰는 오버 헤드를 피할 수 있습니다.
초기화하지 않고 남아있을 수있는 전체 클래스를 만들지 않고이를 수행하는 방법이 될 것입니다.
정말로 원한다면 생성자없이 POD (일반 오래된 데이터 구조)를 만든 다음 몇 가지 추가 기술을 사용하여 초기화를 보장 할 수있는 방법으로 사용할 수 있습니다. 예를 들어, 구조를 추가하거나 기이하게 반복되는 템플릿 패턴을 사용하는 파생 클래스를 만듭니다.
그런 다음 초기화하지 않으려면 POD를 직접 사용할 수 있습니다.
초기화되지 않은 생성자를 만드는 방법을 이미 알고 있습니다. 초기화되지 않은 값과 초기화 된 생성자가 공존 할 수 있는지 여부는 문제입니다. –
기본 계약자가 항상 호출됩니다. 할 수있는 "트릭"이 많이 있지만이 동작을 원하는 이유와 사용자 코드를 어떻게 보이게 할 것인지에 따라 다릅니다. 데이터 멤버를 사용하지 않고 호출 할 수있는 특별한 생성자를 정의 할 수 있습니다. 아니면 다양한 일을 할 수 있습니다. 하나의 옵션은 ...
템플릿으로도 재생할 수 있습니다.
struct uninitialized_ctor {};
class Foo
{
public:
int x;
Foo() : x(42)
{
std::cout << "Foo::Foo\n";
}
protected:
Foo(uninitialized_ctor const &)
{
std::cout << "Foo::Foo - uninitialized\n";
}
};
struct UninitializedFoo : public Foo
{
UninitializedFoo()
: Foo(uninitialized_ctor())
{
// Does not call base class ctor...
std::cout << "UninitializedFoo\n";
}
};
int main(int, char *[])
{
Foo foo1;
UninitializedFoo foo2;
Foo * f1 = new Foo();
Foo * f2 = new UninitializedFoo();
std::cout << foo1.x << '\n' << foo2.x << '\n' << f1->x << '\n' << f2->x << '\n';
}
하지만 - 그것은 당신의 진짜 목적이 무엇인지에 따라 달라집니다 ... 어떻게 코드에 영향을 미치기 사용자 ...
집계 클래스 유형은 기본적으로 동작을 당신이 좋아 :
struct Foo { int a; int b; };
Foo x; // x.a, x.b uninitialized
Foo * p = new Foo(); // p->x, p->y value-initialized, i.e. zero
Foo y { 1, 2 }; // brace-initialization does what you think
Foo z { }; // brace-initialization can also "fake" value-init for automatics
집계의 경우 default 및 value 초기화가 반복적으로 구성원에게 전파됩니다.
struct Bar
{
int a;
int b;
Bar() : a() { } // no b!
Bar(int a_, int b_) : a(a_), b(b_) { }
};
Bar x; // x.a is value-, x.b is default-initialized
이 아마도 당신이 이런 식으로 뭔가를 할 수 :
사소한 소멸자가 필요
template<typename T>
struct uninitialized {
static_assert(std::is_trivially_destructible<T>::value,"T must have trivial dtor");
alignas(T) char raw[sizeof(T)];
template<typename... Us>
T &initialize(Us &&... us) {
return *(new (raw) T(std::forward<Us>(us)...));
}
T &get() { return reinterpret_cast<T&>(raw); }
};
때문에 그렇지 않으면 당신 '당신은 또한 초기화되지 않은 멤버 잎이 아닌 집계를 만들 수 있습니다 물론
객체를 적절히 파괴하기 위해 객체가 구축되었는지 여부를 추적해야합니다.
나는 (당신이 단지 위의 숫자를 모으는 POD에 대해 말하지 않는 한) 꽤 없다고 확신합니다. –
'int b = int();'는 실제로 _value-initialization_이며, 단지 스칼라에 제로 - 초기화의 효과가 있습니다. 그리고 내가 당신의 동기를 정확하게 추측한다면, 당신은 [Boost.Optional] (http://www.boost.org/libs/optional/)을 볼 것을 제안 할 것입니다. – ildjarn
초기화되지 않은 변수를 원한다면 어떤 근거가 있습니까? 유스 케이스를 설명하면 아마도 더 좋은 방법이 될 것입니다. – bta