Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.67/6: Рейтинг темы: голосов - 6, средняя оценка - 4.67
1 / 1 / 1
Регистрация: 02.03.2013
Сообщений: 184
1

Конструктор копирования

29.02.2020, 09:11. Показов 1217. Ответов 12

Доброго времени суток!
Есть маленький класс:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class MyClass
{
private:
    int x = 5;
    int y = 10;
 
    double xx = 10.5;
public:
    MyClass();
    ~MyClass() = default;
 
    MyClass(MyClass const & other);
    MyClass& operator=(MyClass const & other);
 
    void print() { std::cout<<"I'm MyClass"<<std::endl;}
};
 
MyClass::MyClass()
    :x(5), y(10), xx(10.5)
{
     std::cout<<"Construct"<<std::endl;
}
 
MyClass::MyClass(MyClass const & other)
    :x(other.x), y(other.y), xx(other.xx)
{
    std::cout<<"Copy Construct"<<std::endl;
}
Никак не могу понять, почему в данном коде вызывается конструктор копирования:
C++
1
2
3
4
5
6
7
8
9
10
11
12
std::vector<MyClass> bar()
{
    std::vector<MyClass> tmps;
    MyClass m;
 
    std::cout<<"befor push_back !"<< std::endl;
    tmps.push_back(m);
    tmps.push_back(m);
    std::cout<<"after push_back !"<< std::endl;
 
    return std::move(tmps);
}
Метод push_back() принимает объект по ссылке. Так почему происходит вызов конструктора копирования? К сожалению не могу привести скриншот, который показывает вызов конструктор копирования.
0

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
29.02.2020, 09:11
Ответы с готовыми решениями:

Не могу сделать чтобы класс содержал основной конструктор и конструктор копирования
Разработать класс ThreeAngle для работы с плоскими треугольниками. В качестве членов-данных...

Конструктор класса, конструктор копирования запускается не тот который нужен
Есть такой конструктор: Neuron::Neuron(int iType_activation_funk) { this-&gt;iType_act =...

Не могу правильно сделать конструктор и конструктор копирования и принадлежность точки с заданными координатами треугольнику
#include &quot;stdafx.h&quot; #include &lt;iostream&gt; #include &lt;conio.h&gt; #include &lt;windows.h&gt; #include...

Конструктор инициализации, конструктор копирования, деструктор
Я сделал почти задание по перегрузке операторов. Осталось одно, тоесть три: конструктор...

12
749 / 352 / 72
Регистрация: 10.06.2014
Сообщений: 2,371
29.02.2020, 09:19 2
schoolboy_,
Потому что push_back хоть и принимает объект по ссылке, но внутри себя копирует исходный элемент в своё хранилище элементов.

Добавлено через 1 минуту
Если исходный элемент создаётся только для добавления в вектор, используйте emplace_back для размещения элемента в контейнере напрямую без копирования
1
С чаем беда...
Эксперт CЭксперт С++
9170 / 4685 / 1272
Регистрация: 18.10.2014
Сообщений: 10,609
29.02.2020, 09:19 3
Цитата Сообщение от schoolboy_ Посмотреть сообщение
Так почему происходит вызов конструктора копирования?
Как это "почему"? Вы копируете ваш объект m в вектор. Разумеется, происходит вызов конструктора копирования.
1
1 / 1 / 1
Регистрация: 02.03.2013
Сообщений: 184
29.02.2020, 09:27  [ТС] 4
Если всё равно происходит копирование в внутреннее хранилище, то почему такой код не компилируется:
C++
1
2
3
4
    std::unique_ptr<MyClass> ptr (new MyClass());
 
    std::vector<std::unique_ptr<MyClass>> ptrs;
    ptrs.push_back(ptr);
Такой код компилируется и работает:
C++
1
2
3
4
    std::unique_ptr<MyClass> ptr (new MyClass());
 
    std::vector<std::unique_ptr<MyClass>> ptrs;
    ptrs.push_back(std::move(ptr));
Добавлено через 2 минуты
TheCalligrapher, как мне понять, что я копирую элемент в вектор?
Вот у меня есть такой код:
C++
1
2
3
4
void copy(MyClass& m)
{
    m.print();
}
Конструктор копирования не вызывается.
Метод push_back() имеет похожую сигнатуру. В нём копирование происходит.
0
749 / 352 / 72
Регистрация: 10.06.2014
Сообщений: 2,371
29.02.2020, 09:28 5
schoolboy_,
unique_ptr не копируемый тип, но перемещаемый.
1
1 / 1 / 1
Регистрация: 02.03.2013
Сообщений: 184
29.02.2020, 09:29  [ТС] 6
Undisputed, но если внутри произойдёт копирование, как мне сказали, то какая разница в какой момент копировать?
0
749 / 352 / 72
Регистрация: 10.06.2014
Сообщений: 2,371
29.02.2020, 09:34 7
schoolboy_,
Что бы произошло копирование, в данном случае у типа элементов вектора (unique_ptr) должен быть конструктор копирования, а его нет. Поэтому получаете ошибку. В случае с версией где используется move вы перемещаете unique_ptr в вектор, копирования не происходит и код компилируется. Копирование внутри вектора только в той версии где нет move, не путайте
1
1 / 1 / 1
Регистрация: 02.03.2013
Сообщений: 184
29.02.2020, 09:42  [ТС] 8
Undisputed, примерно понятно.
Вот этот пример, должен противоречить вашей логике.

C++
1
2
3
4
5
6
7
8
9
10
11
std::vector<MyClass> bar()
{
    std::vector<MyClass> tmps;
    MyClass m;
 
    std::cout<<"befor push_back !"<< std::endl;
    tmps.push_back(std::move(m));
    std::cout<<"after push_back !"<< std::endl;
 
    return std::move(tmps);
}
Вызывается всё равно конструктор копирования.
0
749 / 352 / 72
Регистрация: 10.06.2014
Сообщений: 2,371
29.02.2020, 09:56 9
schoolboy_,
а вы реализуйте конструктор перемещения явным образом и напечатайте в нем что нибудь
1
1 / 1 / 1
Регистрация: 02.03.2013
Сообщений: 184
29.02.2020, 10:14  [ТС] 10
Вот мой конструктор копирования:
C++
1
2
3
4
5
6
MyClass::MyClass(MyClass && other)
    :x(other.x), y(other.y), xx(other.xx)
{
    x = y = 0; xx = 0;
    std::cout<<"Move Construct"<<std::endl;
}
Он действительно вызывается. Получается, что он не сильно отличается он конструктора копирования. Видимо, перемещающий конструктор имеет смысл, если у нас есть указатель(как например, в динамическом массиве). Тогда действительно это эффективно. Или в специфических случаях типо мьютекса. Когда этого требует логика.
Undisputed , я прав в своих рассуждениях?
0
749 / 352 / 72
Регистрация: 10.06.2014
Сообщений: 2,371
29.02.2020, 10:25 11
Лучший ответ Сообщение было отмечено schoolboy_ как решение

Решение

schoolboy_,
Верно. Но в данном случае до реализации конструктора перемещения конструктор копирования вызывался не по этой причине. Когда вы реализуете конструктор копирования, компилятор не добавляет конструктор перемещения по умолчанию. Но тем не менее код компилируется потому что результат move может быть привязан к const T&, а это как раз соответствует сигнатуре конструктора копирования. Поэтому он и был вызван.
1
1 / 1 / 1
Регистрация: 02.03.2013
Сообщений: 184
29.02.2020, 10:34  [ТС] 12
Undisputed, спасибо. Вы мне помогали разобраться.
0
С чаем беда...
Эксперт CЭксперт С++
9170 / 4685 / 1272
Регистрация: 18.10.2014
Сообщений: 10,609
29.02.2020, 12:57 13
Цитата Сообщение от schoolboy_ Посмотреть сообщение
Метод push_back() имеет похожую сигнатуру. В нём копирование происходит.
Это не вопрос сигнатуры метода. Это вопрос того, что происходит внутри метода push_back. Внутри метода push_back этот самый push_back будет копировать ваш объект в вектор. Это то, что, по определению, делает метод push_back.

Цитата Сообщение от schoolboy_ Посмотреть сообщение
как мне понять, что я копирую элемент в вектор?
Почитать документацию на метод push_back.

Цитата Сообщение от schoolboy_ Посмотреть сообщение
Он действительно вызывается. Получается, что он не сильно отличается он конструктора копирования.
Отличается или не отличается ли конструктор перемещения от конструктора копирования зависит только от вас: содержимое этих конструкторов пишете вы сами. Что вы там напишете, то и будет.

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

Цитата Сообщение от schoolboy_ Посмотреть сообщение
Видимо, перемещающий конструктор имеет смысл, если у нас есть указатель(как например, в динамическом массиве).
Да, именно так, в "традиционном" понимании перемещения. Однако никто вам не запрещает ввести свое понятие "перемещения". Еще раз: конструкторы копирования и перемещения пишете вы сами. И в чем будут заключаться различия между копированием и перемещением тоже определяете вы сами.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
29.02.2020, 12:57

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

конструктор копирования
Добрый день, не могу разобраться с конструктором копирования : // virtual functions with person...

Конструктор копирования
#include &lt;iostream&gt; #include &lt;cstring&gt; #include &lt;cstdlib&gt; #define SIZE 30 using namespace...

Конструктор копирования в c++
Добрый день, такая задача по с++ Какая ошибка в следующей реализации конструктора копирования по...


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

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.