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