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

时间:2013-02-04 19:56:41

标签: c++ class object methods constructor

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

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

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;
};

在这样的方法中,人们希望创建类NumberArray的未初始化对象,然后“构造”基于this的新对象和参数中的对象? AKA:

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 个答案:

答案 0 :(得分:1)

目前还不完全清楚你要做什么,但如果你想要的只是创建一个新的类实例而没有一个构造函数而不是默认的构造函数,那么就这样做。

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

答案 1 :(得分:1)

您要求的是展示位置。这看起来像这样:

#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而不是自己编写。

答案 2 :(得分:0)

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

如果需要,可以为对象分配足够的内存,并将指向该内存的指针重新解释为指向所需类型的指针。这通常适用于POD,但由于c ++中的多态继承的许多实现(如果不是全部)都将指向vtable的指针添加到多态实例,这种方法通常(如果不是总是)会失败。

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

答案 3 :(得分: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 ++上工作,您必须返回一个指针并且'anonymous'类型必须具有名称,即使它仅限于该函数。

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