Reputation: 6613
The constructor semantics of int/double/etc. are:
int a; // uninitialized
int b = int(); // zero initialized
int c = int(4); // four
Is it possible to define a class with exactly the same behavior? I.e., one that has both uninitialized and initialized default constructors? I believe this is impossible, and currently work around it by making a constructor that compiles only when called with 0, but want to make sure there isn't a way to exactly mimic fundamental types.
Upvotes: 1
Views: 198
Reputation: 136266
If no constructors defined:
struct A { int x; };
A a; // default-initialized (unintialized)
A b = A(); // value-initialized
A c = { 4 }; // four
Upvotes: 2
Reputation: 88155
Perhaps you could do something like this:
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); }
};
trivial destructor is required because otherwise you'd have to keep track of whether the object had been constructed or not in order to destroy it appropriately.
Upvotes: 0
Reputation: 477070
Aggregate class types have essentially the behaviour you like:
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
For aggregates, default- and value-initialization propagate recursively to members.
Of course you can also make a non-aggregate that leaves a member uninitialized:
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
Upvotes: 0
Reputation: 28409
The default contractor will always be called. There are lots of "tricks" you can do, but it depends on why you want this behavior, and what you want the user code to look like. You can define a special constructor that just doe not do anything with the data members and call that. Or, you can do lots of different things... one option is this...
You can also play with templates...
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';
}
BUT -- it depends on what your real goal is... and how it impacts users of the code...
Upvotes: 1
Reputation: 58578
"uninitialized construction" is oxymoronic.
Lack of initialization in construction only occurs as a result of bugs (failing to recursively construct the entire object).
If a C++ class has a constructor, it is called. If for any reason it cannot be called, then that situation is erroneous (for instance wrong construction arguments passed that don't match any constructor).
A C++ class can contain members which are of basic types, and its constructors can neglect to initialize those members.
This could be exploited for optimization: if you have a complex initialization which happens later, you can avoid the overhead of writing to those members.
That would be the way to do it, rather than trying to create an entire class that can be left uninitialized.
If you really want that, a way to emulate it would be to create a POD (plain old datastructure) without any constructors, and then use some additional techniques so that it can be used in ways that guarantee its initialization. For instance make a derived class from it which adds construction, or make use of the curiously repeating template pattern, etc.
Then you can still use the POD directly if you want it not initialized.
Upvotes: 2
Reputation: 16168
class A {
public:
A() {}
};
A* a = (A*)malloc(sizeof(A));
(kids, don't do this at home. Don't do this at all!)
Upvotes: -1
Reputation: 20272
It is impossible, because as opposed to the built-in types, your class constructor will always be called.
If you really want to do "uninitialized" object (why ???? Don't you have enough bugs because of uninitialized variables?), you'll have to do tricks with placement new
, probably.
Upvotes: 2