move constructor c++ 11

xoki87

для демонстрации примера работы move constructor я написал следующий пример
class Move
{
private:
int* a;
int _size;
public:
Move(int size): _size(size), a(new int[size])
{
cout<<"new Move object of size "<<_size<<" is being created and initialized"<<endl;
}
Move(Move& other):_size(other._size), a(new int [other._size])
{
cout<<"the copy constructor is working"<<endl;
for(int i=0;i<other._size;i++) a[i]=other.a[i];
}
Move(Move && other);
~Move()
{
cout<<"the destructor is working"<<endl;
delete [] a;
}
Move& operator=(const Move & other)
{
cout<<"ordinary assignment operator working"<<endl;
if(this!=&other)
{
delete [] a; // frees the existing resourse
_size=other._size;
a=new int[_size];
for(int i=0;i<other._size;i++) a[i]=other.a[i];
}
}
};
после объявил функцию, возвращающую обьект типа move
Move move_func()
{
int n;
cout<<"enter the value for n"<<endl;
cin>>n;
Move obj(n);
obj.fill();
return obj;
}
после написал следуюшее
Move a=move_func();
cout<<a<<endl;
но при этом не работает ни move constructor + объект не учитывается, я что то не понимаю с move cnstructor или что? компилил на ж++ и явно прописывал -std=g++11

Maurog

ты бы хоть пример попроще выложил, да и цельным куском
предположу, что тут дело в NRVO

Maurog

предположу, что тут дело в NRVO
наблюдаем: http://ideone.com/E6Thas

istran

А где реализация move конструктора?

istran

Собственно, у тебя нигде move конструктор не вызывается. Я добавил: http://ideone.com/zdTe84

Maurog

нигде move конструктор не вызывается. Я добавил
спасибо, забыл про него :o

xoki87

сорри, он был в спп файле
Move::Move(Move && other)
{
_size=other._size;
a=other.a;
cout<<"move constructor is at work"<<endl;
other._size=0;
other.a=NULL;
}

xoki87

вот полностью
#include <iostream>
using namespace std;
class Move
{
private:
int* a;
int _size;
public:
Move(int size): _size(size), a(new int[size])
{
cout<<"new Move object of size "<<_size<<" is being created and initialized"<<endl;
}
Move(Move& other):_size(other._size), a(new int [other._size])
{
cout<<"the copy constructor is working"<<endl;
for(int i=0;i<other._size;i++) a[i]=other.a[i];
}
Move(Move && other)
{
_size=other._size;
a=other.a;
cout<<"move constructor is at work"<<endl;
other._size=0;
other.a=NULL;
}
~Move()
{
cout<<"the destructor is working"<<endl;
delete [] a;
}
Move& operator=(const Move & other)
{
cout<<"ordinary assignment operator working"<<endl;
if(this!=&other)
{
delete [] a; // frees the existing resourse
_size=other._size;
a=new int[_size];
for(int i=0;i<other._size;i++) a[i]=other.a[i];
}
}
void fill()
{
int n;
for(int i=0;i<_size;i++)
{
cout<<"enter the next element"<<endl;
cin>>n;
a[i]=n;
}
}
friend ostream& operator<<(ostream& of, const Move& obj)
{
of<<"this is class output mechanism"<<endl;
for(int i=0;i<obj._size;i++) of<<obj.a[i]<<" ";
of<<endl<<"end of the output for the class object"<<endl;
}

};
Move move_func();
int main()
{
Move a=move_func();
cout<<a<<endl;
return 0;
}
Move move_func()
{
Move obj(5);
obj.fill();
return obj;
}
вот резудьтат
enter the next element
1
enter the next element
2
enter the next element
3
enter the next element
4
enter the next element
5
this is class output mechanism
1 2 3 4 5
end of the output for the class object
the destructor is working
не понятно, почему не выдает сообщения о том, что вызывается move constructor ы выдает сооющение о том, что создается только один объект

bleyman

RVO/NRVO (return value optimization/named return value optimization), говорят же тебе. Оно относится и к передаче temporary values как параметров, кстати.
Попробуй с -fno-elide-constructors.

rosali

Да напиши просто в move_func что-нибудь похитрее, например
Move move_func(int n)
{
if (n == 0) {
Move obj(5);
obj.fill();
return obj;
} else {
return move_func(n-1);
}
}

xoki87

спс, я правильно понимаю, что по этой же причине прога a печатает move-constructor , а моя нет,?

bleyman

Я твою не читал ваще, посмотрел на стрёмно отформатированный код и nope nope nope http://imgur.com/gallery/y4bEI5r
Вот стандарт C++11: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n333... (последняя ревизия перед стандартизированием). ctlr-f там "copy elision", и прочитай полстранички текста.
Хоррор явно вызывает std::move, которое на самом деле ничего не делает кроме а) изменяет тип value на rvalue-reference (move constructable from) (реально, сама функция — тупой тайпкаст), б) в качестве unintended side effect (что интересно, кстати) отрубает copy elision потому что эта оптимизация не умеет случаться одновременно и при передаче параметра, и при возвращении значения.
То есть протянул временное значение через функцию которая тупо возвращает его — нет, нет для тебя copy elision. Ну, вызов move constructor не намного хуже, плюс в реальности ты будешь использовать std::move только в ситуациях где copy elision так и так не срабатывает, так что не надо париться.

istran

а) изменяет тип value на copy-constructable (реально, сама функция — тупой тайпкаст)
Что? Не на rvalue-reference?

bleyman

Ну я это и имел в виду, понятно же. Простите, не вполне тверез и пишу как я об этом у себя в голове думаю. И да, move-constructable-from конечно. Отредактировал коммент.

istran

Я так и не понял до конца, как rvalue-reference работают. Т.е. как ими пользоваться понимаю, но почему так работает не очень.
Вот почему в этом случае:

A a;
A&& rvra = a;
A b = a;

вызывается конструктор копирования, а в этом:

A a;
A b = std::move(a);

move-конструктор? Хотя std::move возвращает ту же самую rvalue reference на a.
Или как работает perfect forwarding:

template <class T>
void proxy(T&& x)
{
impl(std::forward<T>(x));
}

Может кто-нибудь на пальцах объяснить?

Maurog

Может кто-нибудь на пальцах объяснить?
классический труд: http://thbecker.net/articles/rvalue_references/section_01.ht...

Whoman-in-white

move-конструктор? Хотя std::move возвращает ту же самую rvalue reference на a.
вроде как rvalue может передаваться только неименованый объект. Вот эти std::move и std::forward и возвращают значение, которые как rvalue потом считаются

Dimon89

Может кто-нибудь на пальцах объяснить?
Есть отличнейшая лекция Мейерса на эту тему:
http://www.youtube.com/watch?v=BezbcQIuCsY
Первые три минуты можно пропустить, там реклама его новой книги, а вот потом как раз std::move и std::forward

Dimon89

Вот эти std::move и std::forward и возвращают значение, которые как rvalue потом считаются
std::forward возвращает rvalue только если это возможно. Т.е. у тебя может быть такой код:

template <T>
void func(T&& param) {
return std::forward<T>(param);
}

В этом случае функция вернет rvalue только если param действительно пришёл как rvalue.

Maurog

Есть отличнейшая лекция Мейерса на эту тему:
спасибо, просмотрел всю

Dimon89

спасибо, просмотрел всю
Если что, он 9-11 июня проведет тренинг в Яндексе на эту тему (три полных рабочих дня с утра до вечера)

istran

А где подробности можно почитать? Не получается нагуглить, только нашел в твиттере, что будет стоить 9к.

Maurog

А где подробности можно почитать? Не получается нагуглить
я использовал не гугл : http://tech.yandex.ru/events/cpp-party/june-msk/talks/1954/ :grin:

Dimon89

я использовал не гугл : http://tech.yandex.ru/events/cpp-party/june-msk/talks/1954/
...и промахнулся.
http://tech.yandex.ru/events/yagosti/msk-jun-2014/

Dimon89

А где подробности можно почитать? Не получается нагуглить, только нашел в твиттере, что будет стоить 9к.
Официальное объявление вот: http://tech.yandex.ru/events/yagosti/msk-jun-2014/
Стоить действительно будет 9к. На данный момент вроде как все места разобраны, но можно написать на ya-yandex.ru чтобы сообщили если места появятся.

Maurog

...и промахнулся
это как бы говорит о качестве поиска :grin:
письмо написал, но что-то сомневаюсь, что места будут

istran

Я тоже написал; ответили, что даже в список ожидания не запишут, потому что желающих слишком много. Зато пригласили на C++ party.

Maurog

Зато пригласили на
ну это уже не то =\
Оставить комментарий
Имя или ник:
Комментарий: