<br>Hi Stuart,<br><br>--------------------------------------------------------------<br><div class="gmail_quote">On Fri, May 28, 2010 at 1:24 PM, Stuart Golodetz <span dir="ltr"><<a href="mailto:itk@gxstudios.net">itk@gxstudios.net</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div bgcolor="#ffffff" text="#000000">
Hi Luis,<br>
<br>
Thanks for the helpful response.<div class="im">1) When writing functions that take an image as an argument,<br><blockquote type="cite">
we usually use a Raw pointer instead of a Smart Pointer.<br>
<br>
The reason is that SmartPointers will not do polymorphism.<br>
<br>
That is, if you use smart pointers, you can call that function<br>
later with an argument that is a derived class of that image <br>
type.<br>
</blockquote></div>
Not sure I follow what you mean here - if SmartPointers don't support
polymorphism, then doesn't that mean that this sort of thing won't work?<br>
<br>
struct B { virtual ~B() {} };<br>
struct D : B {};<br>
void f(itk::SmartPointer<B> b) {}<br>
...<br>
itk::SmartPointer<D> d;<br>
f(d);<br>
<br></div></blockquote><div><br>Exactly. <br>This code above doesn't work.<br><br>Here is a full example that illustrates the case:<br><br>----------------------------------------------------<br><br>#include "itkImage.h"<br>
#include "itkObject.h"<br><br>class B : public ::itk::Object<br>{<br>virtual ~B() {} <br>};<br><br>class D : public B {};<br><br>void f(itk::SmartPointer<B> b) {}<br>void g( B * b) {}<br><br>int main()<br>
{<br> itk::SmartPointer<D> d;<br> g(d); // This works<br> f(d); // This doesn't<br> return 0;<br>}<br><br><br>---------------------------------------------------<br><br> </div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div bgcolor="#ffffff" text="#000000">
Whereas this always works by the rules of the language:<br>
<br>
void f(B *b) {}<br>
D *d;<br>
f(d);<br>
<br></div></blockquote><div>-------------------------<br><br>Yes,<br>This is the case that support polymorphism.<br><br>------------------------- <br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div bgcolor="#ffffff" text="#000000">
I think I would understand what you mean if your last paragraph said
"That is, if you use *raw* pointers..." [emphasis mine]. Or am I
getting the wrong end of the stick? :)<div class="im"><br></div></div></blockquote><div>------------------------<br><br>My mistake.<br>Thanks for pointing this out.<br><br>When I wrote<br><br>> That is, if you use smart pointers, you can call that function<br>
> later with an argument that is a derived class of that image <br>
> type.<br>
<br>I actually meant to write<br><br>> That is, if you use *raw* pointers, you can call that function<br>
> later with an argument that is a derived class of that image <br>
> type.<br>
<br>Sorry about the mishap.<br><br> ----------------------------------------------------------------------------</div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div bgcolor="#ffffff" text="#000000"><div class="im">
<blockquote type="cite"> If you look at most ITK filters, you will find that
raw pointers<br>
are used in the API, for passing and receiving images.<br>
<br>
However, when we call those functions we pass a SmartPointer<br>
to them (since SmartPointers know how to cast themselves as<br>
raw pointers).<br>
<br>
<br>
2) The only case in which you may want to pass an image<br>
SmartPointer as argument to a function is when you are<br>
creating that image inside the function. <br>
<br>
In that case, passing the SmartPointer by reference is<br>
a reasonable choice.<br>
</blockquote></div>
I think I've been trying to use itk::SmartPointer as a
boost::shared_ptr, which may not be the best plan :) The idea being
that the pointed-to image or whatever won't get destroyed as long as
I'm holding an itk::SmartPointer to it, so I can construct it
somewhere, pass the itk::SmartPointer into a function, store a copy of
the itk::SmartPointer somewhere else and not worry if the original
itk::SmartPointer to the image no longer exists.<br>
<br>
What I've been missing is that itk::SmartPointer appears to use
*intrusive* reference-counting (i.e. the reference count is stored in
the image itself), so that if I pass in a raw image pointer to a
function I can then construct a separate itk::SmartPointer the other
end from it that will share the reference count with the original
itk::SmartPointer. Is that right?</div></blockquote><div><br><br>That's exactly right.<br><br>The actual "reference count" is stored in the image.<br>More specifically in the member variable:<br><br> m_ReferenceCount<br>
<br>which is defined in itkLightObject.h : line 141.<br><br>and the image inherits it through the chain:<br><br>itk::LightObject<br>itk::Object<br>itk::DataObject<br>itk::ImageBase<br>itk::Image<br><br><br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div bgcolor="#ffffff" text="#000000"><div class="im"><br>
<blockquote type="cite">3) Please note that the construction<br>
<br>
const Image::ConstPointer & ptr ....;<br>
<br>
prevents the internal mechanisms of the SmartPointer <br>
from working, since the "const" keyword prevents the "ptr"<br>
variable from changing. (strictly speaking it prevents the<br>
smart pointer from calling the non-const method Register()<br>
on the object that it points to).<br>
</blockquote></div>
Offhand, I think that could be easily changed by making Register() and
UnRegister() const methods, since that would only have the effect of
making m_Pointer itself const, not the ObjectType it points to:<br>
<br>
/** The pointer to the object referrred to by this smart pointer. */<br>
ObjectType* m_Pointer;<br>
<br>
void Register() --> const <--<br>
{ <br>
if(m_Pointer) { m_Pointer->Register(); }<br>
}<br>
<br>
void UnRegister() --> const <--<br>
{<br>
if(m_Pointer) { m_Pointer->UnRegister(); }<br>
}<br>
<br></div></blockquote><div><br><br>Yes, <br>Ideally these methods should have been "const".<br>Since the reference count of the object doesn't<br>really imply a change in its state.<br><br> </div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div bgcolor="#ffffff" text="#000000">
I haven't really looked at the implications that would have elsewhere
though - any thoughts?<br>
<br></div></blockquote><div><br><br>The implications are huge... :-/<br><br>In 2002 we attempted to fix the lack of <br>const-correctness in the pipeline, and<br>the effects propagated all over the toolkit<br>to the point where we have to give up.<br>
<br>In order to fix the lack of const-correctness <br>in the pipeline your will have to rewrite the<br>pipeline from scratch. <br><br><br>Something that,<br>may or may not happen as part of ITKv4....<br><br><br><br></div>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><div bgcolor="#ffffff" text="#000000">
Cheers,<br>
Stu<div><div></div><br></div></div></blockquote></div><br>