boost :: bind внутренней копии / копии? - PullRequest
4 голосов
/ 14 марта 2012

Я надеялся понять, какие внутренние копии функционального объекта делает boost :: bind. Поскольку конструкторы этих объектов, кажется, не вызываются, я предположил, что это своего рода «очень поверхностное копирование», поэтому я ввел динамическое распределение памяти, чтобы вызвать некоторые ошибки. Однако вывод во время выполнения кода ниже, по-видимому, указывает три дополнительных вызовов деструктора для внутренних копий, сделанных связыванием.

using namespace std;
using namespace boost;

class M{
    int *somedata;
public:
    M(){ somedata=new int[5]; cout<<"from cstr\n"; somedata[1]=0;}
    ~M(){cout<<"from dstr\n"; delete somedata;}

    int operator()(int i){ cout<<++somedata[i]<<endl; return 0;}
};


int main()
{
    M instM;

    bind<int>(instM,1)();
    //bind<int>(&M::operator(),&instM,1)(); //this works with no errors, of course

    instM(1); //would not change the order of output

    return 0;
}

На выходе ... представлены некоторые дополнительные головоломки - например. почему первое событие dstr наступает перед вызовом operator ()? Также обратите внимание на «2» перед последним неудачным вызовом деструктора.

from cstr
from dstr
1
from dstr
bind_copy(73365) malloc: *** error for object 0x1001b0: double free
*** set a breakpoint in malloc_error_break to debug
from dstr
bind_copy(73365) malloc: *** error for object 0x1001b0: double free
*** set a breakpoint in malloc_error_break to debug
2
from dstr
bind_copy(73365) malloc: *** error for object 0x1001b0: double free
*** set a breakpoint in malloc_error_break to debug

Итак, вопрос в том, может ли кто-нибудь кратко объяснить, в каком порядке и какие копии делает связывание?

... После некоторого размышления я понял, что bind просто использует (здесь по умолчанию) конструктор копирования. После предоставления какой-либо пользовательской версии этого cstr (с выделением памяти и версией копии "as-deep-as-one-желания") вывод становится чистым (как и должно быть), но загадка остается: есть three вызовы конструктора копирования. Таким образом, в этом случае boost :: bind создает три копии объекта функции. Почему и в каком порядке? (Для вложенных boost :: binding это может привести к довольно взрывному росту числа внутренних копий.)

Вывод с определенным cp-cstr и добавлением некоторых «маркеров наследия» («P» = родитель, каждый cp cstr добавляет «-C»):

 from cstr P
 from cp cstr P-C
 from cp cstr P-C-C
 from cp cstr P-C-C-C
 from dstr P-C-C
 P-C-C-C:1
 from dstr P-C-C-C
 from dstr P-C
 P:1
 from dstr P

1 Ответ

2 голосов
/ 14 марта 2012

См. здесь :

По умолчанию bind создает копию предоставленного объекта функции. boost :: ref и boost :: cref могут использоваться для хранения ссылки на объект функции, а не на копию. Это может быть полезно, когда объект функции не копируемый, дорогой для копирования или содержит состояние; конечно, в этом случае программист должен гарантировать, что функциональный объект не будет уничтожен, пока он еще используется.

...