Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

Implicit Move when returning a local object

Boost , The Boost C++ Libraries BoostBook Documentation Subset , Chapter 23. Boost.Move

Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext

Стандарт C++ определяет ситуации, когда операция неявного перемещения безопасна, и компилятор может использовать ее в случаях, когда оптимизация возвратного значения (Named) не может быть использована. Типичный случай использования — это когда функция возвращает названный (не временный) объект по значению, и следующий код будет идеально компилироваться в C++11:

//Even if movable can't be copied
//the compiler will call the move-constructor
//to generate the return value
//
//The compiler can also optimize out the move
//and directly construct the object 'm'
movable factory()
{
   movable tmp;
   m = ...
   //(1) moved instead of copied
   return tmp;
};
//Initialize object
movable m(factory());

В компиляторах без ссылок на rvalue и некоторых несоответствующих компиляторах (например, Visual C++ 2010/2012) строка, отмеченная (1), вызовет ошибку компиляции, поскольку подвижный не может быть скопирован. Использование явного ::boost::move(tmp) обойдет это ограничение, но в компиляторах C++11 оно будет кодироваться неоптимально (поскольку компиляция не может использовать (N)RVO для оптимизации копии/перемещения).

Boost.Move предлагает дополнительный макрос под названием BOOST_MOVE_RET, который можно использовать для облегчения этой проблемы, получая портативную семантику перемещения по возврату. Давайте воспользуемся представленным ранее классом movable с классами copyable (тип только для копирования), copy_movable (можно копировать и перемещать) и non_copy_movable (некопируемый и недвижимый):

//header file "copymovable.hpp"
#include <boost/move/core.hpp>
//A copy_movable class
class copy_movable
{
   BOOST_COPYABLE_AND_MOVABLE(copy_movable)
   int value_;
   public:
   copy_movable() : value_(1){}
   //Move constructor and assignment
   copy_movable(BOOST_RV_REF(copy_movable) m)
   {  value_ = m.value_;   m.value_ = 0;  }
   copy_movable(const copy_movable &m)
   {  value_ = m.value_;   }
   copy_movable & operator=(BOOST_RV_REF(copy_movable) m)
   {  value_ = m.value_;   m.value_ = 0;  return *this;  }
   copy_movable & operator=(BOOST_COPY_ASSIGN_REF(copy_movable) m)
   {  value_ = m.value_;   return *this;  }
   bool moved() const //Observer
   {  return value_ == 0; }
};
//A copyable-only class
class copyable
{};
//A copyable-only class
class non_copy_movable
{
   public:
   non_copy_movable(){}
   private:
   non_copy_movable(const non_copy_movable&);
   non_copy_movable& operator=(const non_copy_movable&);
};

и построить общую фабричную функцию, которая возвращает вновь построенное значение или ссылку на уже построенный объект.

#include "movable.hpp"
#include "copymovable.hpp"
#include <boost/move/core.hpp>
template<class Type>
struct factory_functor
{
   typedef Type return_type;
   Type operator()() const
   {  Type t;  return BOOST_MOVE_RET(Type, t);  }
};
struct return_reference
{
   typedef non_copy_movable &return_type;
   non_copy_movable &operator()() const
   {  return ncm; }
   static non_copy_movable ncm;
};
non_copy_movable return_reference::ncm;
//A wrapper that locks a mutex while the
//factory creates a new value.
//It must generically move the return value
//if possible both in C++03 and C++11
template <class Factory>
typename Factory::return_type lock_wrapper(Factory f)
{
   typedef typename Factory::return_type return_type;
   //LOCK();
   return_type r = f();
   //UNLOCK();
   //In C++03: boost::move() if R is not a reference and
   //has move emulation enabled. In C++11: just return r.
   return BOOST_MOVE_RET(return_type, r);
}
int main()
{
   movable m            = lock_wrapper(factory_functor<movable>     ());
   copy_movable cm      = lock_wrapper(factory_functor<copy_movable>());
   copyable c           = lock_wrapper(factory_functor<copyable>    ());
   non_copy_movable &mr = lock_wrapper(return_reference             ());
   return 0;
}

Предупреждение: При использовании этого макроса в несоответствующих компиляторах или компиляторах C++03 движение будет выполняться даже в том случае, если стандарт C++11 его не допускает (например, возврат статической переменной). Пользователь несет ответственность за использование этого макроса только для возврата локальных объектов, соответствующих критериям C++11. Например:

struct foo
{
   copy_movable operator()() const
   {
      //ERROR! The Standard does not allow implicit move returns when the object to be returned 
      //does not met the criteria for elision of a copy operation (such as returning a static member data)
      //In C++03 compilers this will MOVE resources from cm
      //In C++11 compilers this will COPY resources from cm
      //so DON'T use use BOOST_MOVE_RET without care.
      return BOOST_MOVE_RET(copy_movable, cm);
   }
   static copy_movable cm;
};

Примечание: При возврате временного объекта BOOST_MOVE_REF не требуется, так как правила эллизионного копирования будут работать как на компиляторах C++03, так и на C++11.

//Note: no BOOST_MOVE_RET
movable get_movable()
{  return movable();  }
copy_movable get_copy_movable()
{  return copy_movable();  }
copyable get_copyable()
{  return copyable();  }

PrevUpHomeNext

Статья Implicit Move when returning a local object раздела The Boost C++ Libraries BoostBook Documentation Subset Chapter 23. Boost.Move может быть полезна для разработчиков на c++ и boost.




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.



:: Главная :: Chapter 23. Boost.Move ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-05-19 17:47:37/0.0069890022277832/0