1

int/double/etc 的构造函数语义。是:

int a; // uninitialized
int b = int(); // zero initialized
int c = int(4); // four

是否可以定义具有完全相同行为的类?即,一个同时具有未初始化和已初始化的默认构造函数的构造函数?我相信这是不可能的,目前通过制作一个仅在使用 0 调用时编译的构造函数来解决它,但要确保没有办法完全模仿基本类型。

4

8 回答 8

2

这是不可能的,因为与内置类型相反,您的类构造函数将始终被调用。

如果您真的想做“未初始化”对象(为什么????由于未初始化的变量,您没有足够的错误吗?),您可能不得不使用放置技巧new

于 2012-04-11T21:01:33.800 回答
2

如果没有定义构造函数:

struct A { int x; };

A a; // default-initialized (unintialized)
A b = A(); // value-initialized
A c = { 4 }; // four
于 2012-04-11T21:05:39.417 回答
2

“未初始化的构造”是矛盾的。

构造中缺少初始化仅是由于错误(未能递归构造整个对象)而发生的。

如果 C++ 类有构造函数,则调用它。如果由于某种原因不能调用它,那么这种情况是错误的(例如传递的错误构造参数与任何构造函数都不匹配)。

C++ 类可以包含基本类型的成员,其构造函数可以忽略初始化这些成员。

这可以用于优化:如果您有一个稍后发生的复杂初始化,您可以避免写入这些成员的开销。

那将是这样做的方法,而不是尝试创建一个可以保持未初始化的整个类。

如果你真的想要,模拟它的一种方法是创建一个没有任何构造函数的 POD(普通旧数据结构),然后使用一些额外的技术,以便可以以保证其初始化的方式使用它。例如从它创建一个派生类来增加构造,或者利用奇怪重复的模板模式等。

然后,如果您不想初始化 POD,您仍然可以直接使用它。

于 2012-04-11T21:14:13.500 回答
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';
}

但是——这取决于你的真正目标是什么......以及它如何影响代码的用户......

于 2012-04-11T21:25:35.490 回答
0

这是不可能的,无论如何都会调用默认构造函数。

于 2012-04-11T21:00:42.327 回答
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
于 2012-04-11T21:27:24.873 回答
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); }
};

微不足道的析构函数是必需的,因为否则您必须跟踪对象是否已构造,以便适当地销毁它。

于 2012-04-11T21:32:08.113 回答
-1
class A { 
public:
    A() {}

};
A* a = (A*)malloc(sizeof(A));

(孩子们,不要在家里这样做。根本不要这样做!)

于 2012-04-11T21:06:47.147 回答