C++ 如何在堆栈和堆对象之间转换

C++ 如何在堆栈和堆对象之间转换,c++,stack,heap,C++,Stack,Heap,例如: Class *_obj1; Class *_obj2; void doThis(Class *obj) {} void create() { Class *obj1 = new Class(); Class obj2; doThis(obj1); doThis(&obj2); _obj1 = obj1; _obj2 = &obj2; } int main (int argc, const char * argv[]

例如:

Class *_obj1;
Class *_obj2;

void doThis(Class *obj) {}

void create() {
    Class *obj1 = new Class();
    Class obj2;

    doThis(obj1);
    doThis(&obj2);

    _obj1 = obj1;
    _obj2 = &obj2;
}

int main (int argc, const char * argv[]) {

    create();

    _obj1->doSomething();
    _obj2->doSomething();

    return 0;
}
这将创建2个对象,创建指向它们的指针,然后main()对每个对象调用一个方法。类对象创建一个char*并在其中存储C字符串“Hello!”;~Class()deallocator释放内存。doSomething()方法使用printf()打印“buff:%s”。很简单。现在,如果我们运行它,我们会得到:

解除锁定
牛:你好
浅黄色:“ø乧”

显然,堆栈对象在这里不起作用-很明显,当函数退出时,指针_obj2指向堆栈中的某个位置。这就是我在上一个问题中使用堆对象的原因,人们告诉我这是“愚蠢的”

因此,第一个问题是:如果我如何将堆栈对象(obj2)转换为堆对象,以便在create()退出后不会释放它?我希望得到一个直截了当的答案,而不是像许多人那样傲慢地说“你做错了”。因为在这种情况下,堆栈对象无法工作,所以堆对象似乎是唯一的方法。编辑:另外,转换回堆栈对象也很有用


第二个问题:堆对象“错误”的具体示例是使用
new
操作符创建一个新的
vector*
如果动态分配STL对象是错误的,那么正确的方法是什么?显然,如果将它们创建为堆栈对象,它会失败,因为它们会立即被释放,但我被告知(同样,由一个非常高级的成员)动态分配它们会损坏堆。那么正确的方法是什么呢?

唯一的方法是复制对象

将声明更改为:

Class_obj2

并分配:


\u obj2=obj2

堆栈对象是在create函数中创建的,一旦超出该函数的作用域,就会被释放。指针无效


您可以将
Class*obj2
更改为
Class obj2
,并通过
obj2=obj2指定(即复制)对象

您必须复制构造一个新的堆对象(
Class*foo=newclass(obj2)
),或者将堆栈对象分配给堆对象(
*obj1=obj2
)。

获取堆栈变量的地址不会神奇地将其转移到堆中。您需要为类编写一个合适的复制构造函数,并使用
\u obj2=new class(obj2)

至于STL容器,它们在堆上分配数据,为什么要在堆上分配容器本身?把它们放在一个范围内,只要你需要它们,就可以让它们存活

因此,第一个问题是:如果我如何将堆栈对象(obj2)转换为堆对象,以便在create()退出后不会释放它?我想要一个直截了当的答案

直截了当的答案是:不能在堆栈和堆之间“转换”对象。正如其他人所指出的,您可以创建位于其他空间中的对象的副本,但仅此而已

第二个问题:堆对象“错误”的具体示例是使用new操作符创建一个新向量*。如果动态分配STL对象是错误的,那么正确的方法是什么?显然,如果您将它们创建为堆栈对象,它会失败,因为它们会立即被释放,但我(同样,一位非常高级的成员)告诉我,动态分配它们会损坏堆

动态分配STL对象本身不会损坏堆。(不知道你在哪里听到的。)

如果要在创建STL对象的函数外部使用堆栈分配的STL对象,则不能,因为对象所在的堆栈空间仅在创建它的函数内部有效

但是,您可以返回对象的副本:

std::vector<char> SomeFunc()
{
    std::vector<char> myvector;
    // myvector.operations ...
    return myvector;
}
std::vector SomeFunc()
{
std::vector myvector;
//myvector.operations。。。
返回myvector;
}
但是,正如我所说的,这将返回对象的副本,而不是原始对象本身——这是不可能的,因为包含对象的堆栈在函数返回后展开

另一种选择是让调用者传入一个引用/指针,指向函数操作的对象,如果这对特定场景有意义:

void SomeFunc(std::vector<char>& destination)
{
    // destination.operations ...
}

void AnotherFunc()
{
    std::vector<char> myvector;
    SomeFunc(myvector);
}
void SomeFunc(std::vector&destination)
{
//目的地操作。。。
}
void AnotherFunc()
{
std::vector myvector;
SomeFunc(myvector);
}

如您所见,您仍然分配了堆栈上的所有内容,并且避免了依赖复制构造函数返回对象副本的(有时会导致)开销。

我想您真的是想问“如何返回在函数中创建的对象?”有几种有效的方法:

  • 在堆上分配并返回指针
  • 使用自动变量并返回其值,而不是指针(编译器将复制它)
  • 让调用方通过指针或引用参数提供存储,并在那里构建对象
因此,第一个问题是:如果我如何将堆栈对象(obj2)转换为堆对象,以便在create()退出后不会释放它

这一行:

_obj2 = &obj2;
改为:

_obj2 = new Class(obj2);  // Create an object on the heap invoking the copy constructor.
我想要一个直截了当的回答,而不是像许多人那样傲慢地说“你做错了”

这是你能得到的最直接的答案。显然,您对C++是新的,因此我确信它不会像预期那样工作,因为您可能在定义“类”类(按可怕的名字)的定义中犯了几个错误。 此外,转换回堆栈对象也很有用

第二个问题:堆对象“错误”的具体示例是使用new操作符创建一个新向量*。如果动态分配STL对象是错误的,那么正确的方法是什么

为什么要动态分配向量。只需在本地创建它

std::vector<std::string> funct()
{
    std::vector<std::string>   vecString;
    // fill your vector here.

    return vecString;  // Notice no dynamic allocation with new,
}
std::vector funct()
{
向量向量字符串;
std::vector<std::string> funct()
{
    std::vector<std::string>   vecString;
    // fill your vector here.

    return vecString;  // Notice no dynamic allocation with new,
}
std::auto_ptr<Class>   x(new Class);