Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.53/58: Рейтинг темы: голосов - 58, средняя оценка - 4.53
 Аватар для Divergence
7 / 7 / 2
Регистрация: 19.06.2013
Сообщений: 174

Std::vector добавить новый элемент собственного класса без использования конструктора копирования

11.11.2014, 21:26. Показов 11546. Ответов 29
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет!
Есть один класс, который я хочу хранить в std::vector. Создать массив, с типом своего класса, грубо говоря.
Естественно, сначала попробовал такое:
C++
1
2
std::vector<MyClass> ClassArray;
ClassArray.push_back ( MyClass );
Вектор мне тут же выдал ошибку, мол, нельзя указывать тип.
Я попробовал так:
C++
1
2
std::vector<MyClass> ClassArray;
ClassArray.push_back ( new MyClass );
Тоже ошибка.
Третья попытка:
C++
1
2
std::vector<MyClass> ClassArray;
ClassArray.push_back ( MyClass() ); //Пробую передать конструктор
Тут, компилятор говорит о том, что у меня не определен конструктор копирования. Хотя я то хочу передать конструктор по умолчанию! Зачем мне конструктор копирования тут? Возможно К.К. нужен вектору для полноценного функционирования - я до конца не разобрался. Но проблема осталась, очень прошу подсказать:
1) Что нужно передать функции push_back, чтобы создать новый элемент?
2) Можно ли как то обойти ограничение на обязательное наличие конструктора копирования, при использовании std::vector?
Буду благодарен за помощь =)
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
11.11.2014, 21:26
Ответы с готовыми решениями:

Emplace в std::map. Как добавить элемент в std::map без копирования?
здравствуйте... есть ли способ не писать так: std::map&lt;int, char&gt; ksa; ksa.emplace(std::piecewise_construct, ...

Добавить элемент на n-e место в std::vector
Блин нарорд... я затупил по жоскому.... у меня std::vector, пытаюсь добавить элемент на n-e место: using namecpace std; ...

Структура программы или наследование, без использования конструктора базового класса
Всем доброго времени суток. Снова прошу вас о помощи! Код располагается по ссылке в спойлере - не вставлю сюда, так как слишком...

29
Модератор
Эксперт С++
 Аватар для zss
13769 / 10962 / 6491
Регистрация: 18.12.2011
Сообщений: 29,236
11.11.2014, 21:36
А так почему нельзя?
C++
1
2
3
std::vector<MyClass> ClassArray;
MyClass MMM;
ClassArray.push_back ( MMM );
2
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12923 / 6790 / 1818
Регистрация: 18.10.2014
Сообщений: 17,179
11.11.2014, 21:48
Цитата Сообщение от Divergence Посмотреть сообщение
Третья попытка:
C++
1
2
std::vector<MyClass> ClassArray;
ClassArray.push_back ( MyClass() ); //Пробую передать конструктор
Это - правильный вариант. Никакого "передать конструктор" тут нет. Откуда вы такое взяли?

Выражение 'T()' в языке С++ создает инициализированный временный объект типа 'T' . В вашем случае этот объект будет инициализироваться вызовом конструктора по умолчанию. Далее этот временный объект будет скопирован в вектор вызовом конструктора копирования. Именно поэтому вам нужен конструктор копирования. Как ни вертитесь, при таком методе добавления объекта вы обязаны иметь в классе конструктор копирования. (В С++11 тут также будет работать move-конструктор, но это отдельная песня).

Тут скорее возникает вопрос, каким образом вы умудрились остаться без этого конструктора. Конструктор копирования обычно неявно генерируется компилятором. Если у вас его нет, это значит, что в вашем классе понаписано что-то такое, что предотвратило создание нормального конструктора копирования. Вы часом не умудрились написать конструктор копирования руками с неконстантной ссылкой в качестве параметра? Или вы сделали его private?

Если в классе по какой-то уважительной причине все таки нет доступного конструктора копирования, то создать объект в векторе таки можно в С++ при помощи методов группы 'emplace'. В данном случае

C++
1
2
std::vector<MyClass> ClassArray;
ClassArray.emplace_back();
1
 Аватар для Divergence
7 / 7 / 2
Регистрация: 19.06.2013
Сообщений: 174
11.11.2014, 21:49  [ТС]
Думал об этом, но выглядит уродливо...
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12923 / 6790 / 1818
Регистрация: 18.10.2014
Сообщений: 17,179
11.11.2014, 21:52
Цитата Сообщение от zss Посмотреть сообщение
C++
1
2
MyClass MMM;
ClassArray.push_back ( MMM );
Если компилятор, используемый ТС, действительно хочет конструктор копирования, но не может его вызвать по какой-то причине, то такой вариант ничего не исправит.
1
lss
941 / 869 / 355
Регистрация: 10.10.2012
Сообщений: 2,706
11.11.2014, 21:58
Цитата Сообщение от Divergence Посмотреть сообщение
Есть один класс, который я хочу хранить в std::vector.
Класс покажите.
0
 Аватар для Divergence
7 / 7 / 2
Регистрация: 19.06.2013
Сообщений: 174
11.11.2014, 22:17  [ТС]
Спасибо большое за совет с emplace! Я его пробовал, но тоже передавал параметры, поэтому были те же самые проблемы! Сейчас попробую!

P.S. Ради интереса, напишу почему нет К.К. Дело в том, что я в классе использую указатель на объект в видеопамяти. Эта память мне выделяется, грубо говоря, фабрикой. И манипулировать я могу только адресом на эту память. Не хотел связываться с К.К. вообще, чтобы не плодить множественные ссылки на одну и ту же область памяти. А прописывать заново выделение памяти, это гигантский гемор, который планировал сделать в самом конце (когда класс будет дописан полностью).

Добавлено через 1 минуту
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Тут скорее возникает вопрос, каким образом вы умудрились остаться без этого конструктора. Конструктор копирования обычно неявно генерируется компилятором. Если у вас его нет, это значит, что в вашем классе понаписано что-то такое, что предотвратило создание нормального конструктора копирования. Вы часом не умудрились написать конструктор копирования руками с неконстантной ссылкой в качестве параметра? Или вы сделали его private?
Здесь Вы как в воду глядели, как раз сегодня на эту деталь напоролся))) google помог))

Добавлено через 1 минуту
Цитата Сообщение от lss Посмотреть сообщение
Класс покажите.
Класс показывать не вижу смысла, он здоровенный, в нем есть как std::vector'ы на видеопамять, так и другие std::vector'ы, кроме того, он у меня (для упрощения кода) разбит на кучу наследников.

Добавлено через 5 минут
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Если в классе по какой-то уважительной причине все таки нет доступного конструктора копирования, то создать объект в векторе таки можно в С++ при помощи методов группы 'emplace'. В данном случае
C++
1
2
std::vector<MyClass> ClassArray;
ClassArray.emplace_back();
Не разрешает мне компилятор emplace_back() без параметров(((((
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12923 / 6790 / 1818
Регистрация: 18.10.2014
Сообщений: 17,179
11.11.2014, 22:25
Цитата Сообщение от Divergence Посмотреть сообщение
Дело в том, что я в классе использую указатель на объект в видеопамяти.
Это означает, что в вашем случае отсутствие конструктора копирования вполне оправдано. Ваш класс действительно является некопируемым.

В такой ситуации в С++ вам следовало бы сделать ваш класс перемещаемым (movable), т.е. определить перемещающий конструктор и оператор присваивания. Тогда вы сможете пользоваться 'push_back' и 'std::move'.

Ну и по-прежнему у вас есть 'emplace'.

Добавлено через 1 минуту
Цитата Сообщение от Divergence Посмотреть сообщение
Не разрешает мне компилятор emplace_back() без параметров(((((
Странно. Старый компилятор?
2
 Аватар для Divergence
7 / 7 / 2
Регистрация: 19.06.2013
Сообщений: 174
11.11.2014, 22:45  [ТС]
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Странно. Старый компилятор?
MSVS 2010
Да, я пока не перешел на 11 стандарт... думал, что это пока не нужно.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12923 / 6790 / 1818
Регистрация: 18.10.2014
Сообщений: 17,179
11.11.2014, 22:52
Цитата Сообщение от Divergence Посмотреть сообщение
Да, я пока не перешел на 11 стандарт... думал, что это пока не нужно.
В языке С++ до стандарта С++11 хранить в векторе разрешалось только копируемые объекты. Это было жестким строгим требованием. Если объект в принципе не копируем, то в рамках языка до С++11 есть фактически только одно решение - хранить в векторе указатели на объекты, а не сами объекты.
1
 Аватар для Divergence
7 / 7 / 2
Регистрация: 19.06.2013
Сообщений: 174
11.11.2014, 22:55  [ТС]
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
В языке С++ до стандарта С++11 хранить в векторе разрешалось только копируемые объекты. Это было жестким строгим требованием. Если объект в принципе не копируем, то в рамках языка до С++11 есть фактически только одно решение - хранить в векторе указатели на объекты, а не сами объекты.
Спасибо большое за разъяснения!)
Но в моем случае использование указателей вместо объектов приведет к кошмару, я решил воспользоваться уродливым вариантом:

C++
1
2
MyClass MMM;
ClassArray.push_back ( MMM );
Так хотя бы все корректно работает...
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12923 / 6790 / 1818
Регистрация: 18.10.2014
Сообщений: 17,179
11.11.2014, 22:58
Цитата Сообщение от Divergence Посмотреть сообщение
использование указателей вместо объектов приведет к кошмару
Кошмар можно минимизировать использованием smart pointers...

Цитата Сообщение от Divergence Посмотреть сообщение
C++
1
2
MyClass MMM;
ClassArray.push_back ( MMM );
Так хотя бы все корректно работает...
В смысле??? Т.е. код

C++
1
ClassArray.push_back ( MyClass() );
ругается на отсутствие конструктора копирования, а код

C++
1
2
MyClass MMM;
ClassArray.push_back ( MMM );
не ругается? Как такое возможно?
1
lss
941 / 869 / 355
Регистрация: 10.10.2012
Сообщений: 2,706
12.11.2014, 00:10
Цитата Сообщение от Divergence Посмотреть сообщение
я решил воспользоваться уродливым вариантом:
C++
1
2
MyClass MMM;
ClassArray.push_back ( MMM );
Интересно, в чём здесь уродливость?
0
 Аватар для Divergence
7 / 7 / 2
Регистрация: 19.06.2013
Сообщений: 174
12.11.2014, 00:13  [ТС]
Прошу прощения, одно маленькое замечание: вместо push_back, я использовал emplace_back...
И да, так работает, кроме того, я даже проверил, что объекты создаются правильно, так что сомнений нет.

Добавлено через 2 минуты
Цитата Сообщение от lss Посмотреть сообщение
Интересно, в чём здесь уродливость?
Интуитивно ожидается, что должна быть возможность явно передать новый экземпляр объекта из конструктора.
Но это не так (или мы чего-то не знаем) и эта первая строчка выглядит, хм, весьма некрасиво!
0
lss
941 / 869 / 355
Регистрация: 10.10.2012
Сообщений: 2,706
12.11.2014, 00:26

Не по теме:

Цитата Сообщение от Divergence Посмотреть сообщение
Интуитивно ожидается,
Что пишите, то и ожидается. При чём здесь "уродливость"?



Добавлено через 2 минуты
Цитата Сообщение от Divergence Посмотреть сообщение
одно маленькое замечание: : вместо push_back, я использовал emplace_back...
Действительно, маленькое... То есть, совсем по-другому...
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12923 / 6790 / 1818
Регистрация: 18.10.2014
Сообщений: 17,179
12.11.2014, 00:33
Цитата Сообщение от Divergence Посмотреть сообщение
Прошу прощения, одно маленькое замечание: вместо push_back, я использовал emplace_back...
Я все равно не вижу, как это может спасти ситуацию, если у объекта нет конструктора копирования.

А, кажется въехал. Если конструктор копирования есть, но объявлен с параметром-неконстатной ссылкой, то тогда действительно будет именно так. Т.е. конструктор копирования вы таки написали.

Но тогда возникает вопрос: почему ваш конструктор копирования объявлен с параметром-неконстатной ссылкой? И вы вроде говорили, что не хотели возиться с копированием таких объектов. Что же тогда делает конструктор копирования? Можно на него взглянуть?
1
lss
12.11.2014, 01:00

Не по теме:

Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
А, кажется въехал. Если конструктор копирования есть, но объявлен с параметром-неконстатной ссылкой, то тогда действительно будет именно так. Т.е. конструктор копирования вы таки написали.
Ясновиденье в действии...

0
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
12.11.2014, 11:19
Цитата Сообщение от Divergence Посмотреть сообщение
2) Можно ли как то обойти ограничение на обязательное наличие конструктора копирования, при использовании std::vector?
можно, создать массив указателей
C++
1
2
std::vector<MyClass *> vec;
vec.push_back(new MyClass);
самое главное при удалении элементов не забыть почистить память
1
 Аватар для Divergence
7 / 7 / 2
Регистрация: 19.06.2013
Сообщений: 174
12.11.2014, 14:30  [ТС]
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Я все равно не вижу, как это может спасти ситуацию, если у объекта нет конструктора копирования.
А, кажется въехал. Если конструктор копирования есть, но объявлен с параметром-неконстатной ссылкой, то тогда действительно будет именно так. Т.е. конструктор копирования вы таки написали.
Но тогда возникает вопрос: почему ваш конструктор копирования объявлен с параметром-неконстатной ссылкой? И вы вроде говорили, что не хотели возиться с копированием таких объектов. Что же тогда делает конструктор копирования? Можно на него взглянуть?
Сейчас перепроверил, нигде нет конструктора копирования, то есть, использоваться может только К.К. по умолчанию, а он по определению грамотно мой класс скопировать не может. Тем не менее, код действительно работает. Однако, у меня возникло подозрение об утечке памяти:
Мы создаем локальный объект
C++
1
MyClass NewClass;
Он создан локально в функции и по завершению функции, память под него будет помечена освобожденной, тем не менее, я использую его тут
C++
1
ArrayClass.emplace_back ( NewClass );
У меня ощущение, что после выхода из функции, ArrayClass[x] будет ссылаться на память, которая считается свободной и в любой момент может быть использована для чего-то другого.
Подозрения справедливы?

Добавлено через 3 минуты
Цитата Сообщение от aLarman Посмотреть сообщение
можно, создать массив указателей
C++
1
2
std::vector<MyClass *> vec;
vec.push_back(new MyClass);
самое главное при удалении элементов не забыть почистить память
Забавная идея, однако мне никак не приходит в голову, каким образом после этого память нужно будет очищать...
Например, мне скоро понадобится удалить последний элемент из вектора vec. Я пишу: vec.pop_back(). После этого, я не смогу написать вот так:
C++
1
delete vec[Last.Elemene];
Или нужно сначала удалять объект из памяти, и только после этого вызывать pop_back??
0
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
12.11.2014, 15:11
Цитата Сообщение от Divergence Посмотреть сообщение
удалять объект из памяти, и только после этого вызывать pop_back??
да
C++
1
2
delete vec.back();
vec.erase(vec.rbegin());//не знаю сработает ли, загуглите точнее :)
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
12.11.2014, 15:11
Помогаю со студенческими работами здесь

Вызов метода из vector(a) в функции main без использования вызова execute внутри класса
Добрый день столкнулся с проблемой, что просто не могу вызвать метод из вектора в функции main. Код выглядит след образом. #pragma...

На основе исходного std::vector<std::string> содержащего числа, создать std::vector<int> с этими же числами
подскажите есть вот такая задача. Есть список . Создать второй список, в котором будут все эти же числа, но не в виде строк, а в виде...

Реализация класса MyString. Стандартная библиотека, std::string, std::vector
как добавить реализацию конкатенации строк через перегрузку оператора &quot;+=&quot; в классе MyString и почему ошибка выдается???#include...

Все случаи использования конструктора копирования
приведите пример демонстрирующий необходимость и все случаи использование конструктора копирования. нужна помощь)))) #include...

Передача функции указатель на элемент std::vector<std::string>
Доброй ночи тем, кому не спится (или живет в другом часовом поясе:p)! Есть функция, требующая в качестве параметра указатель на...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru