0

在方法内部可以从类中创建一个未初始化的对象吗?

这是一些上下文:想象一个构造函数都分配内存的类:

class NumberArray
{
  size_t m_Size;
  int *m_Numbers;

public:
  NumberArray() { m_Size = 1; m_Numbers = new int[1]; m_Numbers[0] = 0; }

  // . . . other methods for manipulating or constructing . . .

  ~NumberArray() { delete[] m_Numbers; }

  // What if I had a method that concatenates two arrays?
  NumberArray ConcatenateWith(const NumberArray &) const;
};

在这样的方法中,人们希望创建一个未初始化的 class 对象NumberArray,然后基于this参数中的对象“构造”一个​​新对象?又名:

NumberArray NumberArray::ConcatenateWith(const NumberArray &other) const
{
  // Mystery manner of creating an uninitialised NumberArray 'returnObject'.
  returnObject.m_Size = m_Size + other.m_Size;
  returnObject.m_Numbers = new int[returnObject.m_Size];
  std::copy(m_Numbers, m_Numbers + m_Size, returnObject.m_Numbers);
  std::copy(other.m_Numbers, other.m_Numbers + other.m_Size, returnObject.m_Numbers + m_Size);
  return returnObject;
}

这样做的最佳方法是什么?基本上,我不希望默认构造函数创建一个大小为 1 的数组,我将删除该数组,然后再分配一个新数组。

4

4 回答 4

1

尚不清楚您要做什么,但是如果您只想创建一个类的新实例并且除了调用的默认构造函数之外没有其他构造函数,那么就这样做。

您所要做的就是创建一个private构造函数,它与默认构造函数具有不同的签名并且不分配内存(或以任何方式与默认构造函数不同);然后在必要时让您的类在内部调用该构造函数。

于 2013-02-05T00:30:03.693 回答
1

您要求的是放置 new。这看起来像这样:

#include <cstdlib>
#include <new>

void* mem = std::malloc(sizeof(T)); // memory for a T (properly aligned per malloc)

T* x = new (mem) T; // construct a T in that memory location
x->~T();            // destruct that T

std::free(mem); // and free the memory

正确地执行此操作(以具有正确管理和对齐内存的异常安全方式)并非易事。您需要注意对象的生命周期。

对于您的问题,您正在准确描述做什么std::vector。它分配未初始化的原始内存并将插入的元素直接构造到该内存中。它的许多代码都致力于使生命周期和内存管理正确且异常安全!

您应该强烈喜欢使用std::vector而不是自己编写。

于 2013-02-05T01:35:52.917 回答
0

据我所知,没有明确定义的方法可以在不调用它的构造函数的情况下创建对象。这与您是否有权访问其公共接口无关,但如果您想限制谁可以调用它,您可以实现私有或受保护的构造函数。从它自己的内部方法创建类的新实例并没有任何限制,事实上,如果你想限制所述对象在哪些条件下创建所述对象的实例,定义一个私有构造函数和一个静态公共方法是很常见的可以创建。

如果你愿意,你可以为一个对象分配足够的内存,并 reinterpret_cast 一个指向该内存的指针到你想要的类型的指针。这通常适用于 POD,但由于 C++ 中多态继承的许多实现(如果不是全部)添加了指向多态实例的 vtable 的指针,因此这种方法通常(如果不是总是)对那些实例失败。

简而言之,我建议创建一个私有构造函数并让一个静态方法调用它,然后执行您需要的任何其他工作。

于 2013-02-04T20:49:56.980 回答
0

我认为这可能与您想要的类似,是一种“匿名”类:

struct test {
    virtual void doSomething() {
        puts("test");
    }
};

struct a {
    test *t() {
        struct b : test {
            void doSomething() {
                puts("b");
            };
        };

        return new b;
    };
};

int main()
{
    a a;

    a.t()->doSomething(); // outputs 'b'
}

但是,由于切片以及new在 C++ 上的工作方式,您必须返回一个指针,并且“匿名”类型必须有一个名称,即使它仅限于函数。

如果您可以编辑 OP 并明确说明您希望通过此完成什么,也许我们可以为您提供更多帮助。

于 2013-02-04T21:05:06.520 回答