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

发布于 2024-10-18 10:11:37 字数 1113 浏览 2 评论 0原文

示例:

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() 对每个对象调用一个方法。 Class 对象创建一个 char* 并存储 C 字符串“Hello!”在其中; ~Class() 释放器释放内存。 doSomething() 方法使用 printf() 打印出“buff: %s”。够简单的。现在,如果我们运行它,我们会得到:

解除分配
浅黄:你好!
浅黄色:ø_ˇ

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

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

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

Example:

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

This creates 2 objects, creates pointers to them, then main() calls a method on each. The Class object creates a char* and stores the C string "Hello!" in it; the ~Class() deallocator frees the memory. The doSomething() method prints out "buff: %s" using printf(). Simple enough. Now if we run it we get this:

Dealloc
Buff: Hello!
Buff: ¯ø_ˇ

Obviously the stack object does not work here - it's obvious that when the function exits the pointer _obj2 is pointing at a location in the stack. This is why I used heap objects in my previous question, which people told me was "stupid".

So, the first question is: if how can I convert the stack object (obj2) to a heap object so it's not deallocated after create() exits? I want a straight answer, not an arrogant "you're doing it wrong" as so many have done. Because in this case stack objects cannot work so heap objects seem to be the only way. EDIT: Also, converting back to a stack object would be useful as well.

The second question: the specific example of heap objects being "wrong" was creating a new vector<string>* using the new operator. If dynamically allocating STL objects is wrong, then what's the right way? Obviously if you create them as stack objects it fails because they're immediately deallocated, but I've been told (again, by a very high-ranking member) that dynamically allocating them can corrupt the heap. So what's the right way to do it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

两人的回忆 2024-10-25 10:11:37

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

直接的答案是:你不能在堆栈和堆之间“转换”对象。你可以创建位于另一个空间的对象的副本,就像其他空间一样已经指出了,但仅此而已。

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

动态分配 STL 对象本身不会损坏堆。 (不知道您可能在哪里听说过。)

如果您想在创建它的函数之外使用堆栈分配的 STL 对象,您不能,因为其中的堆栈空间对象所在的对象仅在创建它的函数内有效。

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

std::vector<char> SomeFunc()
{
    std::vector<char> myvector;
    // myvector.operations ...
    return myvector;
}

不过,正如我所说,这将返回对象的副本,而不是原始对象本身 - 这是不可能的,因为包含该对象的堆栈在函数返回。

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

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

void AnotherFunc()
{
    std::vector<char> myvector;
    SomeFunc(myvector);
}

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

So, the first question is: if how can I convert the stack object (obj2) to a heap object so it's not deallocated after create() exits? I want a straight answer,

The straight answer is: You can't "convert" an object between the stack and heap. You can create a copy of the object that lives in the other space, as others have pointed out, but that's it.

The second question: the specific example of heap objects being "wrong" was creating a new vector* using the new operator. If dynamically allocating STL objects is wrong, then what's the right way? Obviously if you create them as stack objects it fails because they're immediately deallocated, but I've been told (again, by a very high-ranking member) that dynamically allocating them can corrupt the heap.

Dynamically allocating STL objects will not on its own corrupt the heap. (No idea where you might have heard that.)

If you want to use a stack-allocated STL object outside of the function that you created it in, you can't, since the stack space in which the object resides is only valid inside the function that created it.

You can, however, return a copy of the object:

std::vector<char> SomeFunc()
{
    std::vector<char> myvector;
    // myvector.operations ...
    return myvector;
}

As I said, though, this will return a copy of the object, not the original object itself -- that would be impossible, since the stack that contains the object is unwound after the function returns.

One other option is to have the caller pass in a reference / pointer to the object that your function manipulates, if this makes sense for your particular scenario:

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

void AnotherFunc()
{
    std::vector<char> myvector;
    SomeFunc(myvector);
}

As you can see, you've still allocated everything on the stack, and you avoid the (sometimes consequential) overhead of relying on the copy-constructor to return a copy of the object.

千寻… 2024-10-25 10:11:37

所以,第一个问题是:如何将堆栈对象(obj2)转换为堆对象,以便在 create() 退出后它不会被释放?

这一行:

_obj2 = &obj2;

更改为:

_obj2 = new Class(obj2);  // Create an object on the heap invoking the copy constructor.

我想要一个直接的答案,而不是像很多人那样傲慢地“你做错了”。

这是您能得到的最直接的答案。显然你是 C++ 新手,所以我确信这不会按预期工作,因为你可能在类“Class”的定义中犯了一些错误(顺便说一句,名字很糟糕)。

此外,转换回堆栈对象也很有用。

class obj3(*_obj2);  // dereference the heap object pass it to the copy constructor.

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

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

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

    return vecString;  // Notice no dynamic allocation with new,
}

使用new/delete就是像C一样使用C++。你需要阅读的是智能指针。这些对象控制对象的生命周期,并在超出范围时自动删除对象。

std::auto_ptr<Class>   x(new Class);

这里 x 是一个智能指针(类型为 auto_ptr),当它超出范围时,对象将被删除。但是您可以将 auto_ptr 返回给调用函数,它将安全地从函数中转移出来。它实际上比这复杂得多,你需要一本书。

显然,如果您将它们创建为堆栈对象,则会失败,因为它们会立即释放,

当超出范围时就会释放。

但我被告知(再次,由一位非常高级的成员)动态分配它们可能会损坏堆。

如果你做错了。鉴于你的知识,这很有可能。但由于您没有提供类的定义,因此很难验证。

那么正确的做法是什么?

  1. 了解为什么应该使用堆栈对象
  2. 了解什么是智能指针。
  3. 了解如何使用智能指针来控制对象的寿命。
  4. 了解不同类型的智能指针。
  5. 查一下关注点分离是什么(你没有遵循这个基本原则)。

So, the first question is: if how can I convert the stack object (obj2) to a heap object so it's not deallocated after create() exits?

This line:

_obj2 = &obj2;

Change to:

_obj2 = new Class(obj2);  // Create an object on the heap invoking the copy constructor.

I want a straight answer, not an arrogant "you're doing it wrong" as so many have done.

Thats as straight an answer as you can get. Obviously you are new to C++, So I am sure this will nto work as intended because you have probably made a couple of mistakes in the defintion of the class "Class" (by the way terrible name).

Also, converting back to a stack object would be useful as well.

class obj3(*_obj2);  // dereference the heap object pass it to the copy constructor.

The second question: the specific example of heap objects being "wrong" was creating a new vector<string>* using the new operator. If dynamically allocating STL objects is wrong, then what's the right way?

Why do you dynamically allocate the vector. Just create it locally.

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

    return vecString;  // Notice no dynamic allocation with new,
}

Using new/delete is using C++ like C. What you need to read up on is smart pointers. These are obejcts that control the lifespan of the object and automatically delete the object when they go out of scope.

std::auto_ptr<Class>   x(new Class);

Here x is a smart pointer (of type auto_ptr) when it goes out of scope the object will be deleted. But you can return an auto_ptr to the calling function and it will be safely transfered out of the function. Its actually a lot more complicated than that and you need a book.

Obviously if you create them as stack objects it fails because they're immediately deallocated,

Its de'allocated when it goes out of scope.

but I've been told (again, by a very high-ranking member) that dynamically allocating them can corrupt the heap.

If you do it incorrectly. Which given your knowledge is very likely. But hard to verify since you have not provided the definition of Class.

So what's the right way to do it?

  1. Learn why you should use stack objects
  2. Learn what smart pointers are.
  3. Learn how to use smart pointers to control lifespans of objects.
  4. Learn the different types of smart pointers.
  5. Look up what the separation of concerns is (you are not following this basic principle).
木森分化 2024-10-25 10:11:37

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

You have to either copy-construct a new heap object (Class * foo = new Class(obj2)) or assign the stack object to a heap object (*obj1 = obj2).

柏林苍穹下 2024-10-25 10:11:37

唯一的方法是复制对象。

将声明更改为:

Class _obj2;

并赋值:

_obj2 = obj2;

the only way is to copy object.

Change declaration to:

Class _obj2;

and assign:

_obj2 = obj2;

忆梦 2024-10-25 10:11:37

获取堆栈变量的地址不会神奇地将其传输到堆中。您需要为您的类编写适当的复制构造函数并使用_obj2 = new Class(obj2);

至于STL容器,它们无论如何都在堆上分配数据,为什么要在堆上分配容器本身呢?将它们放在一个范围内,只要您需要它们,它们就能保持活力。

Taking the address of a stack variable won't magically transfer it into heap. You need to write a proper copy-constructor for your class and use _obj2 = new Class(obj2);.

As for STL containers, they allocate their data on the heap anyway, why would you want to allocate container itself on the heap? Put them in a scope that will keep them alive as long as you need them.

淡淡绿茶香 2024-10-25 10:11:37

您的堆栈对象是在 create 函数内创建的,一旦超出该函数的范围就会被释放。指针无效。

您可以将 Class* obj2 更改为 Class obj2 并通过 obj2 = obj2; 分配(这意味着复制)对象

Your stack object is created inside the create function and is deallocated as soon you get out of scope of the function. The pointer is invalid.

You could change Class* obj2 to Class obj2 and the assign (which means copy) the object by obj2 = obj2;

落花浅忆 2024-10-25 10:11:37

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

  • 在堆上分配并返回指针
  • 使用自动变量并返回其值,而不是指针(编译器将复制它)
  • 让调用者通过指针或引用参数提供存储,并构建对象那里。

I think you're really trying to ask "How can I return an object created inside my function?" There are several valid ways:

  • Allocate on the heap and return a pointer
  • Use an automatic variable and return its value, not a pointer (the compiler will copy it)
  • Let the caller provide storage, either by pointer or reference parameter, and build your object there.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文