例:
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;
}
Run Code Online (Sandbox Code Playgroud)
这将创建2个对象,创建指向它们的指针,然后main()调用每个对象的方法.Class对象创建一个char*并存储C字符串"Hello!" 在里面; ~Class()解除分配器释放内存.doSomething()方法使用printf()打印出"buff:%s".很简单.现在,如果我们运行它,我们得到这个:
Dealloc
Buff:你好!
Buff:¯ø_
显然堆栈对象在这里不起作用 - 很明显当函数退出指针时_obj2指向堆栈中的某个位置.这就是我在上一个问题中使用堆对象的原因,人们告诉我这是"愚蠢的".
所以,第一个问题是:如果我如何将堆栈对象(obj2)转换为堆对象,那么在create()退出后它不会被释放?我想要一个直接的答案,而不是像许多人那样傲慢的"你做错了".因为在这种情况下堆栈对象无法工作,所以堆对象似乎是唯一的方法.编辑:此外,转换回堆栈对象也是有用的.
第二个问题:堆对象"错误"的具体示例是vector<string>*使用new运算符创建新对象.如果动态分配STL对象是错误的,那么正确的方法是什么?显然,如果你将它们创建为堆栈对象,它会失败,因为它们会被立即释放,但我被告知(再次由一个非常高级别的成员),动态分配它们会破坏堆.那么正确的方法是什么?
所以,第一个问题是:如果我如何将堆栈对象(obj2)转换为堆对象,那么在create()退出后它不会被释放?我想要一个直接的答案,
直接的答案是:您无法在堆栈和堆之间"转换"对象.你可以创建一个生活在另一个空间中的对象的副本,正如其他人指出的那样,但就是这样.
第二个问题:堆对象"错误"的具体示例是使用new运算符创建新的向量*.如果动态分配STL对象是错误的,那么正确的方法是什么?显然,如果你将它们创建为堆栈对象,它会失败,因为它们会被立即释放,但我被告知(再次由一个非常高级别的成员),动态分配它们会破坏堆.
动态分配STL对象本身不会破坏堆.(不知道你可能听说过那个.)
如果要在创建它的函数之外使用堆栈分配的STL对象,则不能,因为对象所在的堆栈空间仅在创建它的函数内有效.
但是,您可以返回该对象的副本:
std::vector<char> SomeFunc()
{
std::vector<char> myvector;
// myvector.operations ...
return myvector;
}
Run Code Online (Sandbox Code Playgroud)
正如我所说的,这将返回对象的副本,而不是原始对象本身 - 这是不可能的,因为包含该对象的堆栈在函数返回后展开.
另一个选项是让调用者传入一个引用/指针指向函数操作的对象,如果这对您的特定场景有意义:
void SomeFunc(std::vector<char>& destination)
{
// destination.operations ...
}
void AnotherFunc()
{
std::vector<char> myvector;
SomeFunc(myvector);
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,您仍然在堆栈中分配了所有内容,并且避免了依赖于复制构造函数返回对象副本的(有时是相应的)开销.
所以,第一个问题是:如何将堆栈对象(obj2)转换为堆对象,以便在 create() 退出后它不会被释放?
这行:
_obj2 = &obj2;
Run Code Online (Sandbox Code Playgroud)
改成:
_obj2 = new Class(obj2); // Create an object on the heap invoking the copy constructor.
Run Code Online (Sandbox Code Playgroud)
我想要一个直接的答案,而不是像很多人那样傲慢地回答“你做错了”。
这是您能得到的最直接的答案。显然你是 C++ 新手,所以我确信这不会按预期工作,因为你可能在类“Class”的定义中犯了一些错误(顺便说一句,名字很糟糕)。
此外,转换回堆栈对象也很有用。
class obj3(*_obj2); // dereference the heap object pass it to the copy constructor.
Run Code Online (Sandbox Code Playgroud)
第二个问题:堆对象“错误”的具体示例是使用 new 运算符创建一个新的 vector<string>* 。如果动态分配STL对象是错误的,那么正确的方法是什么?
为什么要动态分配向量。只需在本地创建它即可。
std::vector<std::string> funct()
{
std::vector<std::string> vecString;
// fill your vector here.
return vecString; // Notice no dynamic allocation with new,
}
Run Code Online (Sandbox Code Playgroud)
使用new/delete就是像C一样使用C++。你需要阅读的是智能指针。这些对象控制对象的生命周期,并在超出范围时自动删除对象。
std::auto_ptr<Class> x(new Class);
Run Code Online (Sandbox Code Playgroud)
这里 x 是一个智能指针(类型为 auto_ptr),当它超出范围时,对象将被删除。但是您可以将 auto_ptr 返回给调用函数,它将安全地从函数中转移出来。它实际上比这复杂得多,你需要一本书。
显然,如果您将它们创建为堆栈对象,则会失败,因为它们会立即被释放,
当它超出范围时,它就会被取消分配。
但我被告知(再次,由一位非常高级的成员)动态分配它们可能会损坏堆。
如果你做错了。鉴于你的知识,这很有可能。但由于您没有提供类的定义,因此很难验证。
那么正确的做法是什么呢?
| 归档时间: |
|
| 查看次数: |
6836 次 |
| 最近记录: |