Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Storing pointer to instance of class with type conversion operator

Reply
Thread Tools

Storing pointer to instance of class with type conversion operator

 
 
Whitney Kew
Guest
Posts: n/a
 
      12-06-2004
Hello,

I have a question regarding type conversion operators. Let's say I
have a simple (nonsensical) class as follows:

class MakeNewInt
{
private:
int* _n;

// By the way, because of the type conversion operator, a
// compiler might not catch an accidental deletion of a
// stack instance - i.e., "delete MakeNewInt(123)" - so,
// add a private operator void*() declaration.
operator void*();

public:
operator int*() const
{
return _n;
}
MakeNewInt(int n) : _n(new int(n)) {}
~MakeNewInt()
{
delete _n;
}
};

Let's also say that I have a method as follows:

void f(int* n)
{
int* q = n;
// Can do other things with q...
}

If I then invoke f() in a main() as such....

int main()
{
f(MakeNewInt(123)); // OK
return 0;
}

....everything is fine; inside f(), I can operate on the pointer q,
knowing that the destructor of MakeNewInt() won't be called until I
exit f().

If, however, I invoke MakeNewInt and attempt to store the result in a
local variable, as such....

int main()
{
int* n = MakeNewInt(123); // n is garbage
return 0;
}

....the destructor of MakeNewInt() has already been called as soon as I
reach the "return 0;" line, and thus the pointer n points to garbage.
Is there anything I can do to allow a caller to use my MakeNewInt class
in this fashion?

Thanks!
Whitney Kew
Software Engineer

 
Reply With Quote
 
 
 
 
Victor Bazarov
Guest
Posts: n/a
 
      12-06-2004
Whitney Kew wrote:
> I have a question regarding type conversion operators. Let's say I
> have a simple (nonsensical) class as follows:
>
> class MakeNewInt
> {
> private:
> int* _n;
>
> // By the way, because of the type conversion operator, a
> // compiler might not catch an accidental deletion of a
> // stack instance - i.e., "delete MakeNewInt(123)" - so,
> // add a private operator void*() declaration.
> operator void*();
>
> public:
> operator int*() const
> {
> return _n;
> }
> MakeNewInt(int n) : _n(new int(n)) {}
> ~MakeNewInt()
> {
> delete _n;
> }
> };
>
> Let's also say that I have a method as follows:
>
> void f(int* n)
> {
> int* q = n;
> // Can do other things with q...
> }
>
> If I then invoke f() in a main() as such....
>
> int main()
> {
> f(MakeNewInt(123)); // OK
> return 0;
> }
>
> ...everything is fine; inside f(), I can operate on the pointer q,
> knowing that the destructor of MakeNewInt() won't be called until I
> exit f().
>
> If, however, I invoke MakeNewInt and attempt to store the result in a
> local variable, as such....
>
> int main()
> {
> int* n = MakeNewInt(123); // n is garbage
> return 0;
> }
>
> ...the destructor of MakeNewInt() has already been called as soon as I
> reach the "return 0;" line, and thus the pointer n points to garbage.
> Is there anything I can do to allow a caller to use my MakeNewInt class
> in this fashion?


int * const & n = MakeNewInt(123);

The object here is bound to a reference to const and shall exist for as
long as the reference exists.

V
 
Reply With Quote
 
 
 
 
Whitney Kew
Guest
Posts: n/a
 
      12-06-2004
Unfortunately, that doesn't work; n points to a pointer that points to
garbage as soon as the statement completes. Plus, I don't want the
caller to have to remember something like that, since I don't
necessarily have control over what the caller writes. I was hoping
that there was some way that I could modify the MakeNewInt class, while
preserving the type conversion operator functionality, so that a caller
could safely make the following call:
int* n = MakeNewInt(123);

Thanks,
Whitney

 
Reply With Quote
 
Victor Bazarov
Guest
Posts: n/a
 
      12-06-2004
Whitney Kew wrote:
> Unfortunately, that doesn't work; n points to a pointer that points to
> garbage as soon as the statement completes.


Your compiler might be broken, then. Binding to a const reference should
keep the temporary around well past the declaration statement, AFAIUI.

Try

int * const & n(MakeNewInt(123));

although AFAIK it shouldn't make any difference.

> Plus, I don't want the
> caller to have to remember something like that, since I don't
> necessarily have control over what the caller writes. I was hoping
> that there was some way that I could modify the MakeNewInt class, while
> preserving the type conversion operator functionality, so that a caller
> could safely make the following call:
> int* n = MakeNewInt(123);


When is the object going to be destroyed, then? Something has to exist
that defines the lifetime of that temporary. In C++ there are three
different limits for a temporary lifetime. Generally it is the full
expression. Then the initialisation (with which you're struggling). And
then there's binding to a const reference. No matter what you do in your
class, you won't be able to change how the language is specified.

You might want to rethink the need for your users to do such a stupid
thing as holding onto a pointer obtained from a temporary object.

V
 
Reply With Quote
 
Whitney Kew
Guest
Posts: n/a
 
      12-06-2004
Hm, strange. I tried your suggestion of:

int * const & n(MakeNewInt(123));

.... and my compiler couldn't even build it.

OK, let me ask another question: My intended use of this class is for
the callers to use it as in the first case...

f(MakeNewInt(123));

.... Could I somehow prevent the user from using it in the second case;
in other words, at compile time, prevent the user from storing a
temporary object?

Thanks much!
Whitney

 
Reply With Quote
 
Whitney Kew
Guest
Posts: n/a
 
      12-06-2004
Unfortunately, that doesn't work; n points to a pointer that points to
garbage as soon as the statement completes. Plus, I don't want the
caller to have to remember something like that, since I don't
necessarily have control over what the caller writes. I was hoping
that there was some way that I could modify the MakeNewInt class, while
preserving the type conversion operator functionality, so that a caller
could safely make the following call:
int* n = MakeNewInt(123);

Thanks,
Whitney

 
Reply With Quote
 
adbarnet
Guest
Posts: n/a
 
      12-06-2004
Do you need to hold on to the pointer in your creating class? If that is a
requirement, then implement the pointer with reference counting, if it isn't
a requirement, then make a static create method returning a std::auto_ptr
(implicitly passing pointer ownership to the caller).

ad


"Whitney Kew" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed) ups.com...
> Hello,
>
> I have a question regarding type conversion operators. Let's say I
> have a simple (nonsensical) class as follows:
>
> class MakeNewInt
> {
> private:
> int* _n;
>
> // By the way, because of the type conversion operator, a
> // compiler might not catch an accidental deletion of a
> // stack instance - i.e., "delete MakeNewInt(123)" - so,
> // add a private operator void*() declaration.
> operator void*();
>
> public:
> operator int*() const
> {
> return _n;
> }
> MakeNewInt(int n) : _n(new int(n)) {}
> ~MakeNewInt()
> {
> delete _n;
> }
> };
>
> Let's also say that I have a method as follows:
>
> void f(int* n)
> {
> int* q = n;
> // Can do other things with q...
> }
>
> If I then invoke f() in a main() as such....
>
> int main()
> {
> f(MakeNewInt(123)); // OK
> return 0;
> }
>
> ...everything is fine; inside f(), I can operate on the pointer q,
> knowing that the destructor of MakeNewInt() won't be called until I
> exit f().
>
> If, however, I invoke MakeNewInt and attempt to store the result in a
> local variable, as such....
>
> int main()
> {
> int* n = MakeNewInt(123); // n is garbage
> return 0;
> }
>
> ...the destructor of MakeNewInt() has already been called as soon as I
> reach the "return 0;" line, and thus the pointer n points to garbage.
> Is there anything I can do to allow a caller to use my MakeNewInt class
> in this fashion?
>
> Thanks!
> Whitney Kew
> Software Engineer
>



 
Reply With Quote
 
Victor Bazarov
Guest
Posts: n/a
 
      12-06-2004
Whitney Kew wrote:
> Hm, strange. I tried your suggestion of:
>
> int * const & n(MakeNewInt(123));
>
> ... and my compiler couldn't even build it.
>
> OK, let me ask another question: My intended use of this class is for
> the callers to use it as in the first case...
>
> f(MakeNewInt(123));
>
> ... Could I somehow prevent the user from using it in the second case;
> in other words, at compile time, prevent the user from storing a
> temporary object?


No. Just like you can't prevent a memory leak in the case

f(new int(123));

(which is probably what you're trying to do). There are some things in
the language that every programmer has to know, and it's not really our
responsibility to provide fool-proof methods for avoiding them. If your
users are so inclined to make such mistakes like holding onto invalid
pointers, they should be programming in Java instead.

V
 
Reply With Quote
 
adbarnet
Guest
Posts: n/a
 
      12-06-2004
There are smart pointer templates you should take a look at - search google,
or look at the Boost or Loki libraries - one form (NoCopy Policy in Loki)
disallows copy and assignment of the pointer variable - you are forced to
use the pointer through an accessor of the containing object. There is no
other way to access the underlying pointer.

You could implement it yourself - but someone's already done it so why
bother?


"Whitney Kew" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed) oups.com...
> Hm, strange. I tried your suggestion of:
>
> int * const & n(MakeNewInt(123));
>
> ... and my compiler couldn't even build it.
>
> OK, let me ask another question: My intended use of this class is for
> the callers to use it as in the first case...
>
> f(MakeNewInt(123));
>
> ... Could I somehow prevent the user from using it in the second case;
> in other words, at compile time, prevent the user from storing a
> temporary object?
>
> Thanks much!
> Whitney
>



 
Reply With Quote
 
David White
Guest
Posts: n/a
 
      12-06-2004
"Whitney Kew" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed) oups.com...
> Hm, strange. I tried your suggestion of:
>
> int * const & n(MakeNewInt(123));
>
> ... and my compiler couldn't even build it.
>
> OK, let me ask another question: My intended use of this class is for
> the callers to use it as in the first case...
>
> f(MakeNewInt(123));
>
> ... Could I somehow prevent the user from using it in the second case;
> in other words, at compile time, prevent the user from storing a
> temporary object?


As far as the class's clients are concerned, what is the difference between
the class you've defined and this one?

class MakeNewInt
{
private:
int _n;
operator void*();
public:
operator int*() const
{
return &_n;
}
MakeNewInt(int n) : _n(n) {}
};

I can't see any difference between them except that your version requires a
lot more work for no benefit (your version needs a copy constructor,
assignment operator and destructor, but mine doesn't). If you agree that the
use of 'new' in your version is redundant, what memory management benefits
could it offer?

DW



 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Storing a C pointer in a Python class instance lallous Python 10 10-06-2009 03:46 PM
std::operator<<(basic_ostream&, type) vs. std::basic_ostream::operator(type)... ? Martin T. C++ 7 03-10-2008 10:42 AM
storing pointer vs storing object toton C++ 11 10-13-2006 11:08 AM
converting base class instance to derived class instance Sridhar R Python 14 02-10-2004 02:47 PM
Cannot refer to an instance member of a class from within a shared method or shared member initializer without an explicit instance of the class. DJ Dev ASP .Net 3 02-08-2004 04:19 PM



Advertisments