【问题标题】:how Objects in C++ stored? in heap or stack?C++ 中的对象是如何存储的?在堆还是栈?
【发布时间】:2020-08-31 04:08:46
【问题描述】:
#include <string>
#include <iostream>



class Type {
public:
    int x;
    Type(int a)
    {
        x = a;
    }

    Type(const Type& type1)
    {
        std::cout << "copy" << std::endl;
    }
};

Type Func() 
{
    Type s(1);
    std::cout << &s << std::endl;
    return s;
}

int main()
{
    Type c = Func();
    std::cout << &c << std::endl;
    std::cout << c.x << std::endl;
    system("pause");
}

C++ 为堆或堆栈中的对象分配内存?在 Func 中,假设“s”是在栈中分配的,那为什么不解构呢?为什么我仍然可以在 main() 中调用它。我很困惑。

【问题讨论】:

  • 有趣的事实:C++ 的设计目的是让您不需要堆或堆栈。最好用动态和自动分配来表述这个问题。如果编写正确,这些将是您的 C++ 编程文本中使用的术语。
  • Type 添加一个析构函数,并在其中放置一个诊断输出,以便您可以看到它何时被调用。示例:ideone.com/n8teQN
  • 函数中的 &s 被解构并返回一个副本,该副本在 main() 中使用。如上所述,定义一个析构函数来观察这一点。
  • 您可能会在这里感到困惑的是a compiler will do anything it can to your code to make it run faster,这包括丢弃不必要的复制。现代 C++ 编译器中的Copy Elision 规则甚至允许消除对复制构造函数的调用,即使存在诸如打印语句之类的可见副作用。例如,它可以静默获取c并通过引用将其传递给func并将其用作s,从而无需构造s并将其复制回c
  • 虽然它通过输出未初始化的变量导致未定义的行为(复制构造函数没有初始化x

标签: c++ object memory


【解决方案1】:

默认情况下,对象存储在堆栈中(除非它们的实现具有动态分配器,例如映射)。如果您有自己的类并将其实例化,它将存在于堆栈中。但是,不建议这样做,因为堆栈应该被认为是一种宝贵而稀缺的资源。如果你有一个重的对象,或者很多轻的对象,最好动态分配它们。

在现代 C++ 版本中,我们有所谓的move semanticsmove constructors(可以由编译器自动生成)。基本上,编译器会优化您的代码。在这种情况下,当s 无论如何都会被销毁时,将对象s 复制到c 是低效的。移动构造函数所做的基本上是从s 中窃取数据并将其直接提供给c(在这种情况下,只需使用c 作为存储s 的内存位置的别名)。

【讨论】:

  • 不用担心。请注意,这也不一定是移动语义。只要您声明了一个复制构造函数the default move constructor is disabled,那么提问者的示例就必须省略。
  • 感谢您的评论。你是对的,我完全忘记了在声明复制构造函数时禁用了移动构造函数。
  • 没有“默认”。声明为局部变量的对象是自动分配的;通过new 初始化的对象是动态分配的。
  • 等等,所以 Type c = Func() 调用移动构造函数,而不是复制构造函数?我怎么能告诉这两个构造函数?什么时候调用move,什么时候调用copy?
  • 在这种情况下不,它没有。正如 user4581301 所说,在声明复制构造函数时,移动构造函数被禁用。在这种情况下,我们可能会看到copy elision。我认为this video 很好地说明了这个过程。
猜你喜欢
  • 2021-06-19
  • 2010-10-13
  • 2017-11-05
  • 2011-08-25
  • 2016-12-27
  • 2014-08-14
  • 2015-03-13
  • 2021-02-05
  • 2015-05-03
相关资源
最近更新 更多