类实例的大小

时间:2010-10-05 16:43:47

标签: c++

我正在使用一个已将new运算符设为私有的类,因此获取实例的唯一方法是编写

Foo foo = Foo()

书写

Foo* foo = new Foo()

不起作用。

但是因为我真的想要一个指向它的指针,我用以下方法模拟它:

Foo* foo = (Foo*)malloc(sizeof(Foo));
*foo = Foo();

这样可以测试指针是否为null,以便知道是否已经初始化。

从实证测试来看,它看起来很有效,但有可能没有足够的空间来分配malloc吗?或者其他东西变得有趣?

---编辑---

A没有提到上下文,因为我实际上并不确定他们为什么禁用新操作符。这个类是约束编程库(gecode)的一部分,我认为可以禁用它来强制指定模型的文档化方法。

我不知道具体数据类型的习惯用语,这看起来更合理。

在指定标准模型时,分配方案可能没问题 - 其中所有内容都在Space派生类中指定为CDT--但在我的情况下,这些实例都是由特定类创建的,然后通过引用表示模型的类的构造函数。

关于我没有使用

的原因
Foo f;
Foo *pf = &f;

这就像在下面做 case 1 ,它会抛出“返回对本地变量的引用”警告

int& f() { int a=5; return a; } // case 1
int& f() { int a=5; int* ap=&a; return *ap; }
int& f() { int* ap=(int*)malloc(sizeof(int)); *ap=5; return *ap; }

case 2 中添加指针时,此警告消失,但我想这是因为编译器丢失了曲目。

所以剩下的唯一选择是 case 3 (没有提到另外,ap是一个类的成员,只有在调用f时才会初始化一次,否则为null ,并且是唯一一个返回对它的引用的函数。这样,​​我确信ap在这种情况下失去意义因为编译器优化它(可能会发生吗?)

但我想这远远超出了原来问题的范围......

5 个答案:

答案 0 :(得分:8)

不要将malloc与C ++类一起使用。在malloc调用类'构造函数的非常重要的方面,newnew不同,但malloc没有。{/ p>

你可以通过几种方式获得指针,但首先要问问自己为什么?您是否尝试动态分配对象?你是否试图将指针传递给其他函数?

如果你传递指针,你可能最好不要传递引用:

void DoSomething(Foo& my_foo)
{
  my_foo.do_it();
}

如果确实需要指针(可能是因为你无法更改DoSomething的实现),那么你可以简单地将指针指向自动:

Foo foo;
DoSomething(&foo);

如果需要动态分配Foo对象,事情会变得有点棘手。出于某种原因,有人提出new操作private。可能是一个非常好的理由。 Foo上可能有一个工厂方法,如:

class Foo
{
public:
  static Foo* MakeFoo();
private:
};

..在这种情况下你应该调用它。否则你将不得不编辑Foo本身的实现,这可能不容易或者做得好。

答案 1 :(得分:4)

小心破坏具体数据类型的习惯用法。

您试图规避new运算符已设为私有的事实,即Concrete Data Type成语/模式。由于特定原因,new运营商可能是私有的,例如设计的另一部分可能取决于此限制。试图绕过这个以动态分配类的实例是试图绕过设计并可能导致其他问题或其他意外行为。我不建议在不彻底研究代码的情况下试图绕过这一点,以确保您了解对类/代码的其他部分的影响。

具体数据类型

  

<强>解决方案

     

...

     

表示程序“内部”的抽象的对象,与计算模型,实现或编程语言紧密相关,应声明为本地(自动或静态)实例或成员实例。集合类(字符串,列表,集合)是这种抽象的示例(尽管它们可能使用堆数据,但它们本身不是堆对象)。它们是具体的数据类型 - 它们不是“抽象的”,而是像int和double一样具体。

class ScopedLock
{
  private:
    static void * operator new (unsigned int size); // Disallow dynamic allocation
    static void * operator new (unsigned int size, void * mem);  // Disallow placement new as well.
};
int main (void)
{
   ScopedLock s; // Allowed
   ScopedLock * sl = new ScopedLock (); // Standard new and nothrow new are not allowed.
   void * buf = ::operator new (sizeof (ScopedLock));
   ScopedLock * s2 = new(buf) ScopedLock;  // Placement new is also not allowed
}
  

无法动态分配ScopedLock对象,标准使用new运算符,nothrow new,以及placement new。

答案 2 :(得分:1)

可能发生的有趣事情是由于没有为*foo调用构造函数。只有当它是POD(成员的简单内置类型+没有构造函数)时才会起作用。否则,当使用赋值时,如果左侧不是该类的有效实例,则它可能无法正常工作。

看来,您仍然可以使用

在堆上有效地分配实例
Foo* p = ::new Foo;

要限制如何创建类实例,最好将声明构造函数设置为私有,并且只允许工厂函数调用它们。

答案 3 :(得分:0)

我对底层代码没有完全的了解。如果其他的东西都没问题,上面的代码是正确的。 malloc()将分配足够的空间,任何有趣的事情都不会发生。但是避免使用奇怪的代码并且直截了当地工作:

Foo f;
Foo *pf = &f;

答案 4 :(得分:0)

包裹它:

struct FooHolder {
  Foo foo;
  operator Foo*() { return &foo; }
};