Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > как хранятся объекты привязанные к boost::function


Автор: boostcoder 3.4.2011, 21:59
к примеру такой код:
Код

void func() {
}


boost::function<void()> f(&func);

тут все понятно. в объект f сохраняется адрес функции.

а теперь такой пример:
Код

#include <iostream>
#include <boost/function.hpp>

struct func {
   void operator()() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
   func() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
   func(const func&) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
   ~func() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};

int main() {
   boost::function<void()> f;
   f = func();
   f();
}

вывод:
Цитата

func::func()
func::func(const func&)
func::func(const func&)
func::func(const func&)
func::func(const func&)
func::func(const func&)
func::func(const func&)
func::func(const func&)
func::~func()
func::~func()
func::~func()
func::~func()
func::~func()
func::func(const func&)
func::~func()
func::func(const func&)
func::~func()
func::~func()
func::~func()
void func::operator()()
func::~func() // выводится при выходе из main()

http://liveworkspace.org/code/cec80337b91f8a48fafaff67ad0d7fb6
в выражении "f = func();" создается временный объект типа нашего функционального объекта. это видно в выводе.
потом куча копирующих конструкторов, деструкторов, оператор() нашего объекта, и еще раз деструктор.
так но где хранится? внутри f ?

Автор: mes 3.4.2011, 22:42
Цитата(boostcoder @  3.4.2011,  20:59 Найти цитируемый пост)
внутри f ?

а где ж еще smile

Добавлено через 37 секунд
Цитата(boostcoder @  3.4.2011,  20:59 Найти цитируемый пост)
потом куча копирующих конструкторов, деструкторов, оператор() нашего объекта, и еще раз деструктор.

вот не куча :
http://liveworkspace.org/code/a6355c17dac080dc71a87de9db42c506

Автор: boostcoder 3.4.2011, 22:48
Цитата(mes @  3.4.2011,  22:42 Найти цитируемый пост)
а где ж еще

а каким образом они туда сохраняются?
т.е. к примеру, наш объект содержит еще и данные, и его sizeof() больше одного. если он таки хранится внутри f, то сначала применяется sizeof() к объекту, потом копирование с помощью memcpy() ? т.е. так все просто? никаких хитростей?

Цитата(mes @  3.4.2011,  22:42 Найти цитируемый пост)
вот не куча

это понятно. просто не ожидал что будет столько конструкторов копирования)

Добавлено через 7 минут и 39 секунд
Цитата(boostcoder @  3.4.2011,  22:48 Найти цитируемый пост)
потом копирование с помощью memcpy() ?

или в этом случае необходим конструктор копирования?

Добавлено через 7 минут и 50 секунд
наверное все же да...

Автор: mes 3.4.2011, 23:08
Цитата(boostcoder @  3.4.2011,  21:48 Найти цитируемый пост)
т.е. так все просто? никаких хитростей?

например так :
http://liveworkspace.org/code/2d90e4f88adedcfbd38251bc13ce73a9

только в реале более хитрый механизм используют..

Добавлено через 57 секунд
Цитата(boostcoder @  3.4.2011,  21:48 Найти цитируемый пост)
 memcpy()

memcpy то причем, тем более что вызываются конструкторы..

Добавлено через 1 минуту и 53 секунды
Цитата(boostcoder @  3.4.2011,  21:48 Найти цитируемый пост)
просто не ожидал что будет столько конструкторов копирования)

у std::function должно быть поменьше.. а у boosta столько из за врапперов.. 

Автор: boostcoder 3.4.2011, 23:11
Цитата(mes @  3.4.2011,  23:08 Найти цитируемый пост)
например так

ужос smile 
все таки хитро оно все..
не думал что настолько...

Автор: mes 3.4.2011, 23:11
Цитата(boostcoder @  3.4.2011,  21:48 Найти цитируемый пост)
 и его sizeof() больше одного. если он таки хранится внутри f, 

ммм..внутри f не значит, что непосредственно включенным в f.. он там просто может не поместится smile

Добавлено через 1 минуту и 10 секунд
Цитата(boostcoder @  3.4.2011,  22:11 Найти цитируемый пост)
все таки хитро оно все..
не думал что настолько... 

еще хитрее, чем я показал smile
насколько я помню, он использует свою vtable.. а не предоставленную компилятором..

Добавлено через 11 минут и 56 секунд
http://www.boost.org/doc/libs/1_46_1/boost/function/function_base.hpp
обратите внимание на union function_buffer
там хранится все.. 

Автор: boostcoder 4.4.2011, 00:31
Цитата(mes @  3.4.2011,  23:11 Найти цитируемый пост)
он там просто может не поместится

вот и я об этом..

Цитата(mes @  3.4.2011,  23:11 Найти цитируемый пост)
насколько я помню, он использует свою vtable.. а не предоставленную компилятором..
http://www.boost.org/doc/libs/1_46_1/boost...nction_base.hpp
обратите внимание на union function_buffer
там хранится все..  

жуть какая...

спасибо.
вопрос закрыт.

Автор: maxim1000 4.4.2011, 09:08
более общий вид этого паттерна - type erasure
в частности, он описан здесь: http://www.mr-edd.co.uk/blog/morph_o_matic (правда, там имени этого не упоминается)

больше можно найти по "google type erasure c++"

Автор: mes 4.4.2011, 15:52
morph_о_matic и type_erasure имхо разные подходы.. хотя я не очень- в этой теме.. 

Автор: maxim1000 4.4.2011, 21:28
Цитата(mes @  4.4.2011,  15:52 Найти цитируемый пост)
morph_о_matic и type_erasure имхо разные подходы..

хм... может быть
а какую разницу видишь?

просто я обычно на более-менее мелкие отличия паттернов внимания не обращаю - всё равно на практике всё более размыто, а вот если там есть что-то бОльшее, мне было бы полезно знать

Автор: mes 4.4.2011, 22:15
Цитата(maxim1000 @  4.4.2011,  20:28 Найти цитируемый пост)
а какую разницу видишь?

хм.. надо подумать как высказать..

 




Автор: mes 4.4.2011, 22:57
вот реализовал два подхода условным кодом ..
надеюсь это объяснит лучше, чем слова :

type erasure :
Код

struct any
{
  any () : obj (NULL) {
  }
 ~any () {
     if (do_delete)
         do_delete (obj);
  }
  any (any const& rhs)
  {
     do_clone  = rhs.do_clone;
     do_delete = rhs.do_delete;
     
     obj = do_clone(rhs.obj);   
  }
  
  template <typename T>
  void operator = (const T& rhs)
  {
     do_clone  = &cloner<T>;
     do_delete = &deleter<T>;
     
     obj = do_clone(&rhs);
  }
  template <typename T>
  static void const* cloner(void const*data)
  {
     return new T(*static_cast<T const*>(data));
  }
  template <typename T>
  static void deleter(void const *data)
  {
      delete static_cast<T const*>(data);
  }
  
  void const* (*do_clone)  (void const*);
  void (*do_delete) (void const*);
  
  void const* obj;
};

http://liveworkspace.org/code/5a463163cc0b94f9e3317e93b454f704

morph_o_matic :
Код

struct any
{
  struct i_obj
  {
    virtual i_obj * clone () =0;
  };
  template <typename T>
  struct obj_wrapper : i_obj
  {
      obj_wrapper (T const& data ) 
         : data(data) {
      }
      
      i_obj * clone () {
        return new obj_wrapper(*this);
      }
      T data;
  };
  
  template <typename T>
  void operator = (const T& rhs)
  {     
     _obj = std::shared_ptr<i_obj>(
         new obj_wrapper<T>(rhs)
     );
  }
  
  std::shared_ptr<i_obj> _obj;
};

http://liveworkspace.org/code/4ef038de40ad65c3fce801599eeaa39b

Автор: maxim1000 5.4.2011, 09:45
если я не ошибаюсь, то они, скорее, отличаются деталями реализации
цель одна - стереть какие-то знания о типе, приведя несколько разных типов к одному

Автор: mes 5.4.2011, 10:59
Цитата(maxim1000 @  5.4.2011,  08:45 Найти цитируемый пост)
если я не ошибаюсь, то они, скорее, отличаются деталями реализации

как по мне, то эта два разных механизма / паттерна, позволяющих придти к одной цели.. 

Цитата(maxim1000 @  5.4.2011,  08:45 Найти цитируемый пост)
цель одна - стереть какие-то знания о типе, приведя несколько разных типов к одному

цель другая - привязать объект _любого_ типа к нужному интерфейсу.. 
но в morph_o_matic никакого затирания типа нет.. просто добавляется связывающий адаптер.. 
а вот в type erasure происходит явное затирание..

Добавлено @ 11:13
Цитата(maxim1000 @  5.4.2011,  08:45 Найти цитируемый пост)
 отличаются деталями реализации

детали реализации и есть суть этих паттернов..  smile 



P.S. подправил any (type_erasure) :
  http://liveworkspace.org/code/2329c3f8c946f64509d9bb7596e7e880

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)