在不调用构造函数的情况下在堆栈上分配内存

ego*_*ard 9 c++

我想在下面的代码中将MyClass保存在堆栈内存中(更简单,更快),但是避免调用默认构造函数:

#include <iostream>

class MyClass {
public:
  MyClass() {
    std::cout << "MyClass()" << std::endl;
  }

  MyClass(int a) {
    std::cout << "MyClass(" << a << ")" << std::endl;
  }

  MyClass(const std::string& a) {
    std::cout << "MyClass(\"" << a << "\")" << std::endl;
  }

  void doStuff() {
    std::cout << "doStuff()" << std::endl;
  }
};

int main(int argc, char* argv[]) {
  bool something;
  if (argc > 1)
    something = 1;
  else
    something = 0;

  MyClass c;
  if (something)
    c = MyClass(1);
  else
    c = MyClass("string");
  c.doStuff();

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

据我所知,避免调用默认构造函数的唯一方法是使用指针,但是我必须在堆中分配并处理内存管理.还有其他方法吗?

jxh*_*jxh 13

如果您不介意使用完全黑客,可以尝试放置new.

char mem[sizeof(MyClass)] alignas(MyClass);
auto custom_deleter = [](MyClass *p){ p->~MyClass(); };
std::shared_ptr<MyClass> c(new (mem) MyClass, custom_deleter);
Run Code Online (Sandbox Code Playgroud)

您可以使用它alignas来确保为您的对象正确对齐分配的自动内存.该custom_deleter函数调用析构函数而不释放内存,这在使用带智能指针的自动内存时是必需的.可在此处找到代码演示.

但是,对于您的问题,存在更优雅的解决方案.您可以使用复制构造函数:

  MyClass c = something ? MyClass(1) : MyClass("string");
  c.doStuff();
Run Code Online (Sandbox Code Playgroud)


Vis*_*nda 5

你是对的.您不可能避免调用默认构造函数,除非您想复制一些代码,如下所示.

if (something) {
    MyClass c(1);
    c.doStuff();
}
else {
    MyClass c("string");
    c.doStuff();
}
Run Code Online (Sandbox Code Playgroud)

我建议您创建堆的对象,但将内存处理委托给另一个类.使用C++ 03,可以使用std :: auto_ptr类.对于C++ 11,不推荐使用auto_ptr,而是可以使用shared_ptr或unique_ptr.

以下是使用shared_ptr的一些示例代码 -

std::shared_ptr<MyClass> c;
if (something)
    c.reset(new MyClass(1));
else 
    c.reset(new MyClass("string"));

c->doStuff();
Run Code Online (Sandbox Code Playgroud)

超出范围时,将自动删除该对象.

通常,建议使用智能指针而不是自己进行内存管理.当您处理可能抛出异常的代码时,这尤其有用.


pho*_*ger 5

本杰明Bannier的建议对我的作品在GCC 4.7.2,没有特殊的编译标志(即默认的优化),或-O0,-O1,-O2,或-O3:

int main(int argc, char* argv[]) {
  bool something;
  if (argc > 1)
    something = 1;
  else
    something = 0;

  MyClass c = something ? MyClass(1) : MyClass("string");

  c.doStuff();

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

当我在GCC 3.4.4(大约2004年),GCC 3.4.6(2006年),GCC 4.2.4(2007年)和GCC 4.7.2(2012年)上尝试时,我得到了相同的结果.