2013-07-23 4 views
3

Как передать интеллектуальный ptr функции, ссылающейся на указатель в качестве параметра?Передача умного указателя на функцию, ссылающуюся на параметр указателя

smart_ptr<T> val; // I have this smart pointer 

// And I want to pass it to this function, so that this function will fill the smart pointer with proper value 
void Foo(T*& sth) 
{ 
    sth = memoryAddress; 
} 

EDIT Теперь я понимаю. Спасибо, ребята, за все ответы!

+0

Возможно, вы имели в виду: 'shared_ptr'? – avakar

ответ

7

Простой ответ заключается в том, что вы не можете. В то время как умный указатель почти наверняка содержит T* где-то внутри, умные указатели применяют всевозможные инварианты, многие из которых могут быть сломанным, если вы в состоянии изменить этот указатель, не проходя через пользовательский интерфейс.Единственное решение - вызвать функцию с необработанным указателем, а затем использовать необработанный указатель для инициализации смарт-указателя , предоставил, что вы уверены, что указатель , который вы получаете, соответствует требованиям интеллектуального указателя (например, , назначенный оператором new).

1

Вы не можете этого сделать. Вы можете передать необработанный указатель, используя «T* raw = val.get()», затем «Foo(raw)», но вы не можете установить необработанный указатель shared_ptr, расположенный внутри Foo. Если вы хотите, чтобы Foo установил shared_ptr, сделайте запрос неконстантным shared_ptr.

Как это:

template<typename T> 
Foo(shared_ptr<T>& ptr) 
{ 
    ptr.reset(memoryAddress); // Or assign it, or make_shared, or whatever. 
} 

shared_ptr<int> intptr; 
Foo(intptr); 

Или еще лучше, сделать Foo Вернуть shared_ptr, а не принимать его по ссылке.

+0

'Foo (val.get())' не следует компилировать. Если это так, ваш компилятор сломан. –

+0

Вы правы. Он работает, если вы пройдете через временное. Я уточню свой ответ. –

+0

Если он может изменить интерфейс на 'Foo', он может также сделать это правильно, а указатель' Foo' _return'. –

4

Ugh, этот API является уродливым.

я буду считать, что функция обещает указатель она «возвращает» владеет ресурсом, который должен быть удален вызывающим в способе, которым smart_ptr делает так, и что smart_ptr может быть инициализирована с произвольным указателя. Это невозможно сделать иначе.

Вы можете просто захватить указатель так же, как и в случае отсутствия умных указателей, а затем поместить его в умный указатель.

T* ptr; 
Foo(ptr); 
smart_ptr<T> val(ptr); 

Это может быть так, что умный указатель уже владеет что-то и вы хотите передать что-то функции, а затем заменить то, что является владельцем смарт-указатель. Это ... даже уродливее.

Я не знаю, будет ли функция владеть ресурсом, в который вы проходите (обычно, я бы этого не ожидал, но поскольку API является уродливым, я не буду к нему ругаться). Это приводит к двум различным сценариям.

Если функция принимает владение ресурса вы проходите, то есть, он заботится об удалении самого указателя, смарт-указателе типа должен быть один, который может отказаться от права собственности на ресурсе, как std::unique_ptr с функцией release() члена. Примечательно, что std::shared_ptr не может этого сделать (считайте, что другие shared_ptr s также могут владеть им).

Таким образом, если предположить, что интеллектуальный указатель имеет такую ​​возможность, и способность быть реинициализирован к произвольному указателя (например, с std::unique_ptr::reset), вы можете сделать следующее:

//smart_ptr<T> val; 
T* ptr = val.release(); 
Foo(ptr); 
val.reset(ptr); 

Если функция не брать на себя ответственность ресурса, все, что требуется, - это возможность повторной инициализации с помощью произвольного указателя.

//smart_ptr<T> val; 
T* ptr = val.get(); 
Foo(ptr); 
val.reset(ptr); 
+3

Я хотел бы убедиться, что возвращенный указатель сначала встретил требование умной указатель. Кто-то, кто способен создать такой сломанный интерфейс, также может использовать 'malloc'. –

+0

@ Да, да, это точно первое предположение в моем втором абзаце. –

+0

Итак, я вижу. Точка о том, что делает функция с параметром в записи, тоже хорошая. _Usually_, такие функции ничего не делают, но вы никогда не знаете. –

Смежные вопросы