Где (в каком сегменте памяти) хранятся объекты (класса) в C++?

Давайте возьмем следующий класс для примера

class Shape{
    public:
      Circle (int x): number(x){}
      virtual area () {return x**2;}

    private:
      int number;
}

В основном мы создаем объекты

int main(){
    Shape *foo = new Shape(8);
    Shape *bar = new Shape(65);
    Shape &obj1 = *foo, &obj2 = *bar;
}

Я считаю, что объекты 1 и 2 хранятся в куче. Это почему? Как побочный вопрос. Влияет ли ключевое слово virtual и / или способ определения объектов (например, obj1 = *foo) на его расположение в памяти?

1 ответ

Существует (в широком смысле) два типа объектов, управляющих памятью:

  1. Объекты могут быть полностью построены во время компиляции
  2. Объект может быть полностью построен только с использованием некоторой информации, которая недоступна до тех пор, пока программа не будет запущена

Например, любой constexpr Объект типа может быть полностью оценен и сконструирован во время компиляции и, как таковой, может быть помещен в сегмент данных памяти в качестве оптимизации (с точки зрения пуриста, это допустимо, но далеко не оптимально, для создания таких объектов во время выполнения. Но это приведет к потере циклов ЦП и увеличению продолжительности инициализации / запуска.

Вот несколько примеров таких объектов:

const char * const helloWorld = "Hello, world!";
struct TSilly{
    TSilly(int _i = 0) : i(_i) {}
    int i;
};
const TSilly silly1;
const TSilly silly2(42);
TSilly silly3;   // doesn't have to be constexpr to qualify for static allocation.
                 // This one you can declare as /*extern TSilly silly3;*/ in
                 // header file and access from other compilation units
static TSilly silly4;  // can be local to compilation unit, too

int main()
{
    return 0;
}

Все остальные объекты должны будут ждать, пока будет построено время выполнения.

Примеры таких объектов:

const char * exeName1; // statically allocated by compiler

int main(int argc, char **argv)
{
    exeName1 = argv[0];  // now points to a string

    // buffer is allocated in free storage (heap) bu variable itself is on stack
    char * exeName2 = new char[strlen(argv[0] + 1];
    strcpy(exeName2, argv[0]); // now contains a COPY of a string

    char exeName3[1024];  // likely allocated on stack, be careful with that as stack space is limited
    strncpy(exeName3, argv[0], 1024); // will COPY at most 1023 characters from a string

    delete [] exeName2;  // don't forget to clean up
    // exename3 will be auto-cleaned when we exit the function

    return 0;
}

Как вы можете видеть, объект в C++ будет помещен в сегмент данных или в свободное хранилище (кучу) в зависимости от его времени жизни.

Только динамически размещенные объекты гарантированно помещаются в свободное хранилище. Я не думаю, что спецификация дает какие-либо обещания относительно использования сегментов данных для статически размещенных объектов - это зависит от компилятора, который выполняет и использует эту оптимизацию.

Для получения дополнительной информации посмотрите "Классы хранения C++".

Есть много продвинутых тем управления памятью, которые вы, возможно, захотите изучить. Наиболее релевантным для этого обсуждения является, вероятно, конструктор на месте, который позволяет иметь объект времени выполнения, созданный в памяти, выделенной в сегменте данных исполняемого файла.

Другие вопросы по тегам