Nano Hash - криптовалюты, майнинг, программирование

Использование объектов или указателей на объекты в качестве членов класса и выделение памяти

Аналогичный вопрос задавали здесь:

Члены класса, которые являются объектами - указатели или нет? С++

поэтому буду краток.

Скажем, у меня есть объект, содержащий три вектора stl. Правильно ли я думаю, что если они являются обычными членами класса, память о них будет «вместе» для всего объекта? например моя память будет выглядеть как 10 блоков вектора A, 5 блоков вектора B, а затем 15 блоков вектора C. Затем, как только я вставлю больше объектов в вектор A, чтобы пространство исчерпало всю структуру, включая вектор B и C, необходимо взолнованный?

Это аргумент в пользу указателей? Или векторы внутри являются только указателем на выделенную память? Тот же вопрос касается списков и т.д.

Существуют ли какие-либо эмпирические правила относительно стоимости перенаправления и стоимости копирования небольших объектов? Может быть, что-то вроде перенаправления 5 указателей = 1 целочисленная копия?

Спасибо

09.05.2011

Ответы:


1

Скажем, у меня есть объект, содержащий три вектора stl. Правильно ли я думаю, что если они являются обычными членами класса, память о них будет «вместе» для всего объекта? например моя память будет выглядеть как 10 блоков вектора A, 5 блоков вектора B, а затем 15 блоков вектора C.

Каждый vector занимает фиксированный размер в содержащем объекте, независимо от количества элементов, хранящихся в данный момент в vector. Вполне вероятно, что value_type из vector (например, vector<int> имеет value_type int) не повлияет на размер самого содержащегося объекта vector: только объем выделенного в куче хранилища, необходимого vector для поддержания емкости хранилища (поэтому они вроде бы будет 8 или 16 или 32 байта каждый, но все равно, но не 10 "блоков" (что бы это ни было), 5 блоков и 15).

Будет ли тогда, когда я вставлю больше объектов в вектор A, чтобы пространство закончилось, вся структура, включая вектор B и C, должна быть перемещена?

Вставка элементов в A может привести только к перемещению существующих элементов в A (при превышении емкости). B и C никогда не могут быть затронуты.

Это аргумент в пользу указателей? Или векторы внутри являются только указателем на выделенную память?

ДА, это аргумент... настолько хороший, что ДА, vectors уже делают использование указателей на непрерывную память, где фактически хранятся value_type элементов.

Тот же вопрос касается списков и т.д.

ДА, list также хранят свои value_type элементы в куче, а размер объекта, внедренного или полученного из list, не зависит от операций над list.

Существуют ли какие-либо эмпирические правила относительно стоимости перенаправления и стоимости копирования небольших объектов? Может быть, что-то вроде перенаправления 5 указателей = 1 целочисленная копия?enter code here

C++ работает на слишком многих платформах, чтобы для этого существовали хорошие эмпирические правила. Даже, скажем, на процессорах x86 различия в наборе инструкций, # ядрах, размерах кэша, поставщике/модели/поколении процессора и т. д. могут быть огромными. Косвенность обходится наиболее дорого, если приводит к ошибкам страниц памяти, а это очень зависит от общей картины выполнения программы на машине. Если вам небезразлично, протестируйте реальные компьютеры, на которых запущена программа, пока не получите статистически значимые и стабильные результаты.

09.05.2011
  • Ура, спасибо, ребята, три совершенно хороших ответа, трудно выбрать один. 09.05.2011

  • 2

    Классы коллекций реализуются внутри с помощью указателей — вам не нужно беспокоиться о том, что им не хватит места. Что касается накладных расходов на копирование, не беспокойтесь об этом, если только вы не доказали профилированием своего кода, что это проблема.

    09.05.2011

    3

    Поскольку std::vector имеют динамический размер, они не могут хранить свои элементы как члены или как массив элементов. Помните, что размер объекта известен во время компиляции.

    Но даже в этом случае есть еще кое-что, что можно сказать о неиспользовании членов-указателей. Рассмотрим этот тип:

    struct fat {
        array<double, 30> data;
        array<long, 30> more_data;
        array<char, 30> too_much_data;
    };
    

    где array может быть std::array, std::tr1::array или boost::array; здесь он просто используется в качестве замены для большого шрифта. Вы правы, что fat объекты будут, ну, большими. Преобразование членов в указатели (или динамические массивы или любой моральный эквивалент) все еще преждевременно: сначала используйте объекты как есть, а затем, если они слишком велики или проблематичны, вы можете вместо этого динамически выделить их членов:

    fat* so_much_stuff = new fat[30]();
    // Better:
    std::vector<fat> get_rid_of_it_already(30);
    

    Семантика значений просто упрощает задачу; только до тех пор, пока не будет слишком много копирования или размера или чего-то еще (сначала измерьте) но не раньше, вы должны использовать (динамические) контейнеры и интеллектуальные указатели (которые сами следуют семантике значений).

    ИЗМЕНИТЬ

    std::vector в целом неплохой (как участник или нет), см. обсуждение с Тони в комментариях.

    09.05.2011
  • Хорошо, что вы подумали об этом и хорошо написали, но ваши рассуждения ошибочны из-за 2 упущений: 1) динамическое выделение с использованием vector<> имеет неоспоримое преимущество изменения размера и продолжения работы, тогда как изменение размера массива во время компиляции тратит память впустую, когда есть меньше элементов, а затем полностью выходит из строя. 2) vector имеет семантику значений (то, что C++ позволяет создавать определяемые пользователем типы с семантикой значений, является критической и очень продуманной функцией языка), и поэтому vector автоматически обрабатываются должным образом деструкторами, сгенерированными по умолчанию, и конструкторы копирования. 09.05.2011
  • @Tony Тони. Вы правы, я не выступаю за использование std::array вместо std::array. Я не советую преждевременно использовать std::vector вместо std::array в качестве члена исключительно на том основании, что это сделает объект более компактным. Выбор между std::array или std::vector (в качестве члена или нет) — это совсем другое обсуждение, и вы уже представили некоторые аргументы по этому вопросу. 09.05.2011
  • @Luc: если ваше предостережение о более компактном объекте предупреждает, что, скажем, vector с размером N не будет таким скудным, как массив размера N, это, безусловно, правда, но векторы определенно вступают в свои права, когда заполненный размер значительно меньше, чем емкость N , а также в изменении размера за пределы текущей емкости по требованию. Семантика значений vectors делает их членами с хорошим поведением, и их следует выбирать вместо массивов общего назначения. Привычное использование array было бы преждевременным выбором, так как обычно трудно выбрать хорошую емкость. Я все еще не уверен, согласны вы или нет? :-) 09.05.2011
  • @ Тони Нет, это не так. Мы также не согласны или не согласны, потому что вы обращаетесь (в своем первом комментарии) к чему-то, чем я не являюсь (в моем ответе). array был использован для иллюстрации и потому, что он появился в вопросе; мой ответ не может быть преждевременным, потому что это предпосылка. 09.05.2011
  • @Luc: массив никогда не упоминается в этом вопросе - только вектор... :-/. В любом случае, не беспокойтесь... 10.05.2011
  • @Tony В вопросе упоминалась возможность того, что размер vector зависит от количества элементов, следовательно, он ведет себя так же, как array. 10.05.2011
  • @Luc: о, достаточно честно... сейчас с тобой. Ваше здоровье. 10.05.2011
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..