Странное поведение C++ со структурами и векторами

Когда я запускаю код:

#include <iostream>
#include <vector>

using namespace std;

struct A_s {
    int *arr;
    unsigned int l;

    A_s(unsigned int size) : l(size) {
        arr = new int[size];
        cout<<'\t'<<arr<<endl;
    }

    ~A_s() {
        delete[] arr;               // works if line is removed
    }
};

vector<A_s> vec;

int main() {
    cout<<"vec 0"<<endl;
    vec.emplace_back(1);

    cout<<"vec 1"<<endl;
    vec.emplace_back(1);

    cout<<"vec 2"<<endl;
    vec.emplace_back(1);

    for(unsigned int i = 0; i < vec.size(); i++) cout<<&vec[i]<<endl;

    cout<<"end"<<endl;
    return 0;
}

Результат:

vec 0
        0x761710
vec 1
        0x761a90
vec 2
        0x761ab0
mingw32-make: *** [Makefile:6: run] Error -1073740940

Программа работает без ошибок, если удалить строку delete[] arr. Вызывается ли деструктор до завершения программы? И даже если это так, почему это вызывает ошибку?

vector выполняет множество операций по копированию и уничтожению копий, изменяя размер и перемещая записи. Это приводит к нарушению правила трех.
user4581301 09.01.2019 22:48
Странное поведение C++ ... - Нет, не странно.
PaulMcKenzie 09.01.2019 22:50

Подсказка: добавьте A_s(A_s &&) { cout << "Move!!" << endl; } и посмотрите, что получится.

Stephan Lechner 09.01.2019 22:51
emplace_back вполне может включать в себя копии. Если emplace_back должен увеличить вектор, записи существующий копируются, если тип не перемещается.
zneak 09.01.2019 22:51
vec 0 0x1e1710 vec 1 0x1e1a90 Move!! vec 2 0x1e1ab0 Move!! Move!! mingw32-make: *** [Makefile:6: run] Error -1073740940 Итак, я думаю, он перемещает объекты ...
Roy Varon 09.01.2019 22:52

@RoyVaron Что касается вашего редактирования, это является дубликат. Вектор также перемещает элементы, когда растет, и здесь вступает в силу правило трех. Еще одно исправление - reserve, поэтому он никогда не растет, но вам лучше подчиняться правилу 3/5/0.

François Andrieux 09.01.2019 22:53

Я понимаю. Поскольку он перемещает объекты, я изменил вектор на vecotr<A_s *>. Я удалю РЕДАКТИРОВАТЬ. Всем спасибо за помощь!

Roy Varon 09.01.2019 22:55

@RoyVaron Независимо от того, используете ли вы сейчас вектор и emplace_back, вы должны хотя бы сделать так, чтобы ваши классы имели правильную семантику копирования.

PaulMcKenzie 09.01.2019 22:56
vector<A_s *> - одна из худших вещей, которые вы можете сделать, потому что 1) вы теперь берете на себя нагрузку управления памятью, которую vector может делать за вас, и 2) вы можете случайно скопировать в другом месте и снова оказаться в этой дыре. Правильное решение - поддержка Правило пяти. В этом случае похоже, что вы не хотите когда-либо копировать, поэтому вы delete конструктор копирования и оператор присваивания, чтобы заблокировать любое копирование. Пример
user4581301 10.01.2019 00:03

Либо сделайте A_s правильной семантикой копирования, либо delete - те функции, которые позволяют копировать, чтобы компилятор мог помечать любое использование копирования. Наличие неработающего класса, плавающего в вашем приложении, и надежда, что он не будет использоваться в ситуации копирования, - не способ решения проблемы.

PaulMcKenzie 10.01.2019 13:26
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
10
44
0

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