By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
455,903 Members | 1,304 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 455,903 IT Pros & Developers. It's quick & easy.

How can I insure that the objects of a class must be allocated in the heap?

P: n/a
Hi,

Maybe this is an simple question. How can I insure that the objects of
a class must be allocated in the heap?

Thanks,
Peng

Nov 9 '05 #1
Share this Question
Share on Google+
10 Replies


P: n/a
Pe*******@gmail.com wrote:
Hi,

Maybe this is an simple question. How can I insure that the objects of
a class must be allocated in the heap?

Thanks,
Peng


Make all the constructors private and then declare friend functions to
allocate objects

class X
{
private:
X();
X(int, int);
X(const X&);
public:
...
friend X* make_X() { return new X(); }
friend X* make_X(int a, int b) { return new X(a, b); }
friend X* copy_X(X* rhs) { return new X(*rhs); }
};

john
Nov 9 '05 #2

P: n/a
* Pe*******@gmail.com:

Maybe this is an simple question. How can I insure that the objects of
a class must be allocated in the heap?
There are two ways: (1) restrict access to constructors _and_ provide
factory functions for all relevant constructors in all relevant classes,
or (2) restrict access to your destructor.

(1)
is covered in the FAQ -- go find! ;-)

(2)
which I like much better (less work, doing things once and for all), at
least until someone tells me what the Big Drawback is, is partially
covered in section 1.3.1 of <url:
http://home.no.net/dubjai/win32cpptut/special/pointers/preview/pointers_01__alpha3.doc.pdf>

In addition to the discussion there -- it's an unfinished document --
you'd probably be a happier and more productive programmer if the
once-and-for-all support includes something like

template<
typename T,
void (*defaultDestructionFunction)(T*) = &::callDelete<T>

class SharedPtr: public boost::shared_ptr<T>
{
private:
typedef boost::shared_ptr<T> Base;
public:
// Ordinary construction:
SharedPtr(): Base() {}
SharedPtr( Base const& r ) throw(): Base( r ) {}
SharedPtr( T* p ): Base( p, defaultDestructionFunction ) {}
template< typename Destroyer >
SharedPtr( T* p, Destroyer d ): Base( p, d ) {}

// Special converting construction:
template< class Y >
SharedPtr( boost::shared_ptr<Y> const& r ) throw(): Base( r ) {}
template< class Y >
explicit SharedPtr( boost::weak_ptr<Y> const& r ): Base( r ) {}
template< class Y >
explicit SharedPtr( std::auto_ptr<Y>& r ): Base( r ) {}
};

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Nov 9 '05 #3

P: n/a
Pe*******@gmail.com wrote:
Hi,

Maybe this is an simple question. How can I insure that the objects of
a class must be allocated in the heap?


First, I do not quite understand, why you would want to do something like
that.

As for how you could go about it, here is an idea: You can make the
constructors private. Now, that sounds silly as it prevents construction.
However, you can have a friend. This way, only the friend class is able to
construct objects. If that friend happens to only allocate objects via new,
then you are fine. E.g.:
#include <algorithm>
#include <iostream>

class handle;

class forbidden {

friend class handle;

int i;

forbidden ( int j = 0 )
: i ( j )
{
std::cout << "created\n";
}

~forbidden ( void ) {
std::cout << "destroyed\n";
}

forbidden ( forbidden const & other );
forbidden& operator= ( forbidden const & other );

public:

int get ( void ) const {
return ( i );
}

int set ( int j ) {
i = j;
return j;
}

}; // class forbidden

class handle {

forbidden* ptr;

public:

handle ( int i = 0 )
: ptr ( new forbidden ( i ) )
{}

handle ( handle const & other )
: ptr ( new forbidden ( other.get() ) )
{}

~handle ( void ) {
delete ptr;
}

handle & operator= ( handle const & other ) {
handle dummy ( other );
std::swap( this->ptr, dummy.ptr );
return ( *this );
}

int get ( void ) const {
return ( ptr->get() );
}

int set ( int i ) {
return( ptr->set(i) );
}

}; // handle

int main ( void ) {
handle x ( 5 );
std::cout << x.get() << '\n';
}
Note that this handle has value semantics. It is quite easy to implement
reference semantics instead.

If you just want to allow pointers to forbidden object but not forbidden
objects, you could do something like this:

#include <algorithm>
#include <iostream>

struct handle;

class forbidden {

friend class handle;

int i;

forbidden ( int j = 0 )
: i ( j )
{
std::cout << "created\n";
}

forbidden ( forbidden const & other );
forbidden& operator= ( forbidden const & other );

public:

int get ( void ) const {
return ( i );
}

int set ( int j ) {
i = j;
return j;
}

~forbidden ( void ) {
std::cout << "destroyed\n";
}

}; // class forbidden

struct handle {

static
forbidden* new_forbidden ( int i = 0 ) {
return( new forbidden ( i ) );
}

}; // handle

int main ( void ) {
forbidden* f_ptr = handle::new_forbidden ( 5 );
std::cout << f_ptr->get() << '\n';
delete f_ptr;
}

Anyway, it just seems like you want to make life harder for the clients of
your code. Generally, that is not a good idea: next week, someone will post
the question as to how your measures can be circumvented.
Best

Kai-Uwe Bux
Nov 9 '05 #4

P: n/a
* Kai-Uwe Bux:
Pe*******@gmail.com wrote:
Hi,

Maybe this is an simple question. How can I insure that the objects of
a class must be allocated in the heap?
First, I do not quite understand, why you would want to do something like
that.


For example, a recursive data structure can/should have a recursive
cleanup operation, which needs all objects to be dynamically allocated.

As for how you could go about it, here is an idea: You can make the
constructors private.


See my earlier reply in this thread for a code-it-once-and-for-all
alternative that, so far!, I like much better... ;-)

In addition to what I wrote there, there is a tools issue: for a class
Foo the Visual 7.1 compiler incorrectly allows it to be used as a member
in a class Bar that doesn't define a destructor, but the compiler issues
a warning, and class Bar will generate errors on all practical usage.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Nov 9 '05 #5

P: n/a
Alf P. Steinbach wrote:
* Kai-Uwe Bux:
Pe*******@gmail.com wrote:
> Hi,
>
> Maybe this is an simple question. How can I insure that the objects of
> a class must be allocated in the heap?


First, I do not quite understand, why you would want to do something like
that.


For example, a recursive data structure can/should have a recursive
cleanup operation, which needs all objects to be dynamically allocated.


Hm, I see what you mean.

However, in such a case, I would probably have some container type and some
node type. The node type would be invisible to the clients of the
container. In that case, I do not see any reason to make myself go through
hoops to make sure that I never create a local node variable (which
actually could be useful, provided you know what you are doing). Usually, I
feel no urge to tie my hands.

On the other hand, there might be dynamic data structures in client
territory, not mediated through iterators. For those, I can see that you
have a valid point. But aren't those dangerous anyway?
Thanks

Kai-Uwe Bux

Nov 9 '05 #6

P: n/a
Kai-Uwe Bux wrote:
Alf P. Steinbach wrote:
* Kai-Uwe Bux:
Pe*******@gmail.com wrote:

> Hi,
>
> Maybe this is an simple question. How can I insure that the objects of
> a class must be allocated in the heap?

First, I do not quite understand, why you would want to do something like
that.


For example, a recursive data structure can/should have a recursive
cleanup operation, which needs all objects to be dynamically allocated.


Hm, I see what you mean.

However, in such a case, I would probably have some container type and some
node type. The node type would be invisible to the clients of the
container. In that case, I do not see any reason to make myself go through
hoops to make sure that I never create a local node variable (which
actually could be useful, provided you know what you are doing). Usually, I
feel no urge to tie my hands.

On the other hand, there might be dynamic data structures in client
territory, not mediated through iterators. For those, I can see that you
have a valid point. But aren't those dangerous anyway?


Although not very common, there are instances when requiring
heap-allocated storage for an object is a necessity. These cases
usually arise whenever an object's lifespan extends beyond the current
scope, or the object is shared across threads or is a member of a
cache.

Relying on every programmer to "know" that a certain class of object
must be allocated on the heap is a surefire way for the program to end
up with a stack-allocated object someday. The reason would be that it
is often not apparent when any of the three situations mentioned above
may apply to an object (or at least not apparent to anyone who hasn't
spent years working on the program). So there has to be a failsafe
mechanism that will catch bugs at the ideal time: before they have been
added to the source code.

Greg

Nov 9 '05 #7

P: n/a
Pe*******@gmail.com wrote:
Hi,

Maybe this is an simple question. How can I insure that the objects of
a class must be allocated in the heap?


The answer to your question is to fix the emotional problem that causes
you to obsess over how people will use the class that you write.

It's like asking ``How can I ensure that only jazz will ever be played
on the guitar that I am building?''

Nov 9 '05 #8

P: n/a
Use a singleton and make sure that the static copy that all the
references refer to is allocated on the heap.

Nov 9 '05 #9

P: n/a
> > Hi,

Maybe this is an simple question. How can I insure that the objects of
a class must be allocated in the heap?


The answer to your question is to fix the emotional problem that causes
you to obsess over how people will use the class that you write.

It's like asking ``How can I ensure that only jazz will ever be played
on the guitar that I am building?''

That's not the same at all and there's no emotional problems with that.
Read previous post by Greg, where he precisely describes cases where
you just have to insure that objects are only heap-allocatable; or,
sometime later, perfectly valid code will behave unexpectedly

Nov 9 '05 #10

P: n/a
Greg wrote:
Kai-Uwe Bux wrote:
Alf P. Steinbach wrote:
> * Kai-Uwe Bux:
>> Pe*******@gmail.com wrote:
>>
>> > Hi,
>> >
>> > Maybe this is an simple question. How can I insure that the objects
>> > of a class must be allocated in the heap?
>>
>> First, I do not quite understand, why you would want to do something
>> like that.
>
> For example, a recursive data structure can/should have a recursive
> cleanup operation, which needs all objects to be dynamically allocated.
[snip]
Although not very common, there are instances when requiring
heap-allocated storage for an object is a necessity. These cases
usually arise whenever an object's lifespan extends beyond the current
scope, or the object is shared across threads or is a member of a
cache.
That objects may need to be dynamically allocated is true. However, I have a
hard time to picture a clear cut case, where that is a reasonable
requirement for *all* objects of a given class type. That, however, is the
issue here.
Relying on every programmer to "know" that a certain class of object
must be allocated on the heap is a surefire way for the program to end
up with a stack-allocated object someday.
Here you make a sweeping generalization from object to class of objects.
The reason would be that it
is often not apparent when any of the three situations mentioned above
may apply to an object (or at least not apparent to anyone who hasn't
spent years working on the program). So there has to be a failsafe
mechanism that will catch bugs at the ideal time: before they have been
added to the source code.

Best

Kai-Uwe Bux

Nov 10 '05 #11

This discussion thread is closed

Replies have been disabled for this discussion.