int / double / etc的构造函数语义。是:
int a; // uninitialized
int b = int(); // zero initialized
int c = int(4); // four
是否可以定义具有完全相同行为的类?即,一个同时具有未初始化和初始化默认构造函数的构造函数?我认为这是不可能的,目前通过制作一个仅在用0调用时编译的构造函数来解决它,但是想要确保没有办法完全模仿基本类型。
答案 0 :(得分:2)
这是不可能的,因为与内置类型相反,您的类构造函数将始终被调用。
如果你真的想做“未初始化的”对象(为什么????由于未初始化的变量,你有没有足够的错误吗?),你可能需要做位置new
的技巧。
答案 1 :(得分:2)
如果没有定义构造函数:
struct A { int x; };
A a; // default-initialized (unintialized)
A b = A(); // value-initialized
A c = { 4 }; // four
答案 2 :(得分:2)
“未初始化的建筑”是矛盾的。
构造中缺少初始化只会由于错误而导致(无法递归构造整个对象)。
如果C ++类有构造函数,则调用它。如果由于任何原因无法调用,那么这种情况是错误的(例如传递的错误构造参数与任何构造函数都不匹配)。
C ++类可以包含基本类型的成员,其构造函数可以忽略初始化这些成员。
这可以被利用来进行优化:如果您稍后进行复杂的初始化,则可以避免写入这些成员的开销。
这就是这样做的方式,而不是试图创建一个可以保持未初始化的整个类。
如果你真的想要它,一种模拟它的方法是创建一个没有任何构造函数的POD(普通旧数据结构),然后使用一些额外的技术,以便它可以保证其初始化的方式使用。例如,从中添加一个派生类,它可以添加构造,或者使用奇怪的重复模板模式等。
如果您不希望它被初始化,您仍然可以直接使用POD。
答案 3 :(得分:1)
将始终调用默认承包商。你可以做很多“技巧”,但这取决于你想要这种行为的原因,以及你希望用户代码看起来像什么。您可以定义一个特殊的构造函数,它只是不对数据成员执行任何操作并调用它。或者,你可以做很多不同的事情......一个选择是......
你也可以玩模板......
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';
}
但是 - 这取决于你的真正目标是什么......以及它如何影响代码的用户......
答案 4 :(得分:0)
这是不可能的,无论如何都会调用默认构造函数。
答案 5 :(得分:0)
聚合类类型基本上具有您喜欢的行为:
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
对于聚合,默认值和值初始化以递归方式传播给成员。
当然,您也可以进行非聚合,使成员未初始化:
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
答案 6 :(得分:0)
也许你可以这样做:
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); }
};
需要简单的析构函数,因为否则你必须跟踪对象是否已被构造,以便适当地销毁它。
答案 7 :(得分:-1)
class A {
public:
A() {}
};
A* a = (A*)malloc(sizeof(A));
(孩子们,不要在家里这样做。根本不要这样做!)