4 / 4 / 5
Регистрация: 25.08.2016
Сообщений: 44
1

перемещающий конструктор

27.10.2017, 10:51. Показов 1751. Ответов 22
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день!
Набрасал простейший класс:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;
 
class A{
    public:
    A(){cout<<"A()"<<endl;}
    A(const A&){cout<<"A(A&)"<<endl;}
    A& operator = (const A&){cout<<"=A(A&)"<<endl; return *this;}
    A(A&&){cout<<"A(A&&)"<<endl;}
    A& operator = (A&&){cout<<"=A(A&&)"<<endl; return *this;}
};
 
int main() {
    A a1;
    A a2(a1);
    A a3((A(a2)));
    return 0;
}
По идеи 3 экземпляр класса должен создаваться с помощью перемещающего конструктора, но вывод на консоль следующий:
A()
A(A&)
A(A&)
Помогите Даше найти перемещающий конструктор)
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
27.10.2017, 10:51
Ответы с готовыми решениями:

Перемещающий конструктор
Можете привести пример реализации перемещающего конструктора?

Перемещающий конструктор по умолчанию
Есть класс содержащий в себе std::unique_ptr. Так как unique_ptr не умеет копироваться, копирующего...

Перемещающий конструктор по умолчанию
Генерируется ли конструктор перемещения для простых структур? Например в таком вариант обмен...

Перемещающий конструктор и оператор перемещающего присваивания
Правильно у меня написаны перемещающий конструктор и оператор присваивания? И исправьте ошибку в...

22
223 / 213 / 80
Регистрация: 26.04.2013
Сообщений: 972
27.10.2017, 11:15 2
C++
1
A a3(std::move(A(a2)))
1
4 / 4 / 5
Регистрация: 25.08.2016
Сообщений: 44
27.10.2017, 11:30  [ТС] 3
Да, так работает, спасибо! Но не очень понятно, что вызыватеся в первоначальном варианте,
C++
1
A a3((A(a2)));
если и ни конструктор копирования и ни конструктор перемещения, то что?
0
223 / 213 / 80
Регистрация: 26.04.2013
Сообщений: 972
27.10.2017, 11:44 4
Цитата Сообщение от teatralaik Посмотреть сообщение
если и ни конструктор копирования и ни конструктор перемещения
к сожалению, точно сказать не могу, но подозреваю, что конструктор копирования не может работать с неименованными объектами, в данном случае это A(a2) - он больше похож на x-value (неименованный и перемещаемый объект, если не ошибаюсь). надо звать спецов
0
119 / 9 / 2
Регистрация: 06.09.2017
Сообщений: 82
27.10.2017, 15:08 5
Цитата Сообщение от teatralaik Посмотреть сообщение
По идеи 3 экземпляр класса должен создаваться с помощью перемещающего конструктора
В A a3((A(a2))); создание бесполезного промежуточного временного объекта исключается и сразу вызывается конструктор копий для копирования из a2. Т.е. эта строка эквивалентна A a3(a2);.

Цитата Сообщение от mat_for_c Посмотреть сообщение
A a3(std::move(A(a2)))
Теперь у нас вызов двух конструкторов, а был вызов одного.
0
223 / 213 / 80
Регистрация: 26.04.2013
Сообщений: 972
27.10.2017, 15:30 6
Цитата Сообщение от animefan Посмотреть сообщение
Теперь у нас вызов двух конструкторов
да, и ничему это не противоречит. скажем, нам надо создать объект а2, потом его копию и ее уже переместить, сохранив при этом a2.
0
119 / 9 / 2
Регистрация: 06.09.2017
Сообщений: 82
27.10.2017, 16:59 7
Цитата Сообщение от mat_for_c Посмотреть сообщение
да, и ничему это не противоречит
При чём тут противоречит или нет? Про вызов двух конструкторов -- это была просто констатация факта.
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
27.10.2017, 18:21 8
Цитата Сообщение от teatralaik Посмотреть сообщение
A a3((A(a2)));
замените на:
C++
1
A a3(A(a2));
0
223 / 213 / 80
Регистрация: 26.04.2013
Сообщений: 972
27.10.2017, 21:27 9
Цитата Сообщение от hoggy Посмотреть сообщение
замените на:
у меня почему-то без move не работает
0
119 / 9 / 2
Регистрация: 06.09.2017
Сообщений: 82
27.10.2017, 21:44 10
mat_for_c, см. предупреждение компилятора https://wandbox.org/permlink/n1IUUjR7fFfktfa4
0
223 / 213 / 80
Регистрация: 26.04.2013
Сообщений: 972
27.10.2017, 21:51 11
Цитата Сообщение от animefan Посмотреть сообщение
см. предупреждение компилятора
но это не объясняет, почему A a3((A(a2))); не вызывает конструктор перемещения. мне уже самому интересно.
0
119 / 9 / 2
Регистрация: 06.09.2017
Сообщений: 82
27.10.2017, 21:56 12
mat_for_c, я ещё в #5 написал почему.
0
309 / 221 / 74
Регистрация: 23.05.2011
Сообщений: 981
28.10.2017, 00:41 13
Оптимизация компилятора срабатывает, поэтому и убирается лишнее создание объектов.
0
21 / 19 / 7
Регистрация: 14.03.2014
Сообщений: 249
28.10.2017, 02:40 14
teatralaik, Я кажется понял.
У вас в третьем случае (A a3((A(a2))) вызывается конструктор копирования для A(a2) и на этом всё так сама конструкция интерпритируется компилятором не как создание объекта, а как объявление функции a3 c типом возвращаемого параметра A.
Из ISO 14882-2003 8.2/1 (в 2011 тоже самое)
The ambiguity arising from the similarity between a function-style cast and a declaration mentioned in 6.8
can also occur in the context of a declaration. In that context, the choice is between a function declaration
with a redundant set of parentheses around a parameter name and an object declaration with a function-style
cast as the initializer. Just as for the ambiguities mentioned in 6.8, the resolution is to consider any construct
that could possibly be a declaration a declaration. [Note: a declaration can be explicitly disambiguated
by a nonfunction-style cast, by a = to indicate initialization or by removing the redundant
parentheses around the parameter name. ] [Example:
struct S {
S(int);
};
void foo(double a)
{
S w(int(a)); // function declaration
S x(int()); // function declaration
S y((int)a); // object declaration
S z = int(a); // object declaration
}
—end example]
Добавлено через 24 минуты
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;
 
class A{
    public:
    A(){cout<<"A()"<<endl;}
    A(const A&) {cout<<"A(A&)"<<endl;}
    A& operator = (const A&){cout<<"=A(A&)"<<endl; return *this;}
    A(A&&){cout<<"A(A&&)"<<endl;}
    A& operator = (A&&){cout<<"=A(A&&)"<<endl; return *this;}
};
 
int main() {
    A a2;
    A a3(A&&(a2)); // 1
    A a4((A&&)a2); // 2
    return 0;
}
В первом случае нет вывода как и пологается по стандарту, во втором случае: A(A&&) ч.т.д.
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
28.10.2017, 10:21 15
Цитата Сообщение от animefan Посмотреть сообщение
я ещё в #5 написал почему.
там - фигня

Цитата Сообщение от mat_for_c Посмотреть сообщение
но это не объясняет, почему A a3((A(a2))); не вызывает конструктор перемещения. мне уже самому интересно.
C++
1
(A(a2))
и
C++
1
A(a2)
разные вещи.

уберите лишние скобочки, и получите copy elision.
то бишь, вызов избыточного конструктора будет оптимизирован.
0
21 / 19 / 7
Регистрация: 14.03.2014
Сообщений: 249
28.10.2017, 10:36 16
hoggy, Я наверно неправильный дал ответ. Правда ?
0
Неэпический
17869 / 10634 / 2054
Регистрация: 27.09.2012
Сообщений: 26,736
Записей в блоге: 1
28.10.2017, 10:54 17
Цитата Сообщение от hoggy Посмотреть сообщение
уберите лишние скобочки, и получите copy elision.
Без этих скобочек получим объявление функции.
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
#include <iostream>
using namespace std;
 
class A{
    public:
    A(){cout<<"A()"<<endl;}
    A(const A&){cout<<"A(A&)"<<endl;}
    A& operator = (const A&){cout<<"=A(A&)"<<endl; return *this;}
    A(A&&){cout<<"A(A&&)"<<endl;}
    A& operator = (A&&){cout<<"=A(A&&)"<<endl; return *this;}
};
 
 
int main()
{
    A a2;
    std::cout << "go\n";
    A a3(A(a2));
    a3(a2);
    std::cout << "Hello, world!\n";
}
 
 
 
A a3(A(a2))
{
    std::cout << "A3 call" << std::endl;
}
http://rextester.com/JSF71819

Цитата Сообщение от teatralaik Посмотреть сообщение
Помогите Даше найти перемещающий конструктор
А всё просто. Зачем при A a3((A(a2))); копировать a2 во временный объект, а потом перемещать временный объект в a3? Можно ж сразу скопировать a2 в a3. Компилятор так и делает.
Добавим ключик -fno-elide-constructors, чтобы "глупый" gcc не умничал:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
using namespace std;
 
class A{
    public:
    A(){cout<<"A()"<<endl;}
    A(const A&){cout<<"A(A&)"<<endl;}
    A& operator = (const A&){cout<<"=A(A&)"<<endl; return *this;}
    A(A&&){cout<<"A(A&&)"<<endl;}
    A& operator = (A&&){cout<<"=A(A&&)"<<endl; return *this;}
};
 
int main() {
    A a2;
    A a3((A(a2)));
    return 0;
}
http://rextester.com/ATXE69409
Цитата Сообщение от вывод
A()
A(A&)
A(A&&)
Добавлено через 3 минуты
Цитата Сообщение от Pechkin80 Посмотреть сообщение
интерпритируется компилятором не как создание объекта
В данном случае "лишние" скобочки ломают компилятору
возможность интерпретировать эту конструкцию как объявление функции.
4
21 / 19 / 7
Регистрация: 14.03.2014
Сообщений: 249
28.10.2017, 10:57 18
Можно немного усложнить жизнь:
A&& ra = A();
A a3(ra);
0
Неэпический
17869 / 10634 / 2054
Регистрация: 27.09.2012
Сообщений: 26,736
Записей в блоге: 1
28.10.2017, 11:00 19
Pechkin80, так перемещение не получите, будет вызван конструктор копирования
0
21 / 19 / 7
Регистрация: 14.03.2014
Сообщений: 249
28.10.2017, 11:04 20
Croessmah, Ну эт понятно что не получу. Потому я это привёл сюда как более сложный случай. Ну там создаётся универсальная ссылка и чтото с ней нехорошее происходит. суть в том что магия скобочек тут уже не действует.
0
28.10.2017, 11:04
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
28.10.2017, 11:04
Помогаю со студенческими работами здесь

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

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

this(Всегда ли вызывается конструктор при не явной передачи объекта в конструктор)
class Test { int i; public: void test(int i) { this -&gt; i = i; } }; Конструктор...

Будет ли определен компилятором конструктор по умолчанию, если есть конструктор с дефолтным параметром?
Добрый день, сразу к делу, есть некий класс class some { int x; public: some(int y = 1)...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru