473,395 Members | 1,578 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

Smart pointer implementation

Is there anything wrong with my attempt (below) at implementing
something resembling a smart pointer?

template < class T >
class SmartPointer
{
private:
T *t;

public:
SmartPointer() {t=new T();}
SmartPointer( const SmartPointer<T> &rhs ) {t=rhs.t;}
T& operator*() const {return(*t);}
T* operator->() const {return(t);}
SmartPointer<T>& operator= ( const SmartPointer<T> &rhs ) {t=rhs.t; return(*this);}
~SmartPointer() {delete t;}
};

The program I wrote to test this crashes, and I wouldn't be at all
surprised to learn that I've made a mistake here somewhere. And no, I
can't use Boost for this.

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Jul 22 '05 #1
24 2153
Christopher Benson-Manica wrote:

Is there anything wrong with my attempt (below) at implementing
something resembling a smart pointer?

template < class T >
class SmartPointer
{
private:
T *t;

public:
SmartPointer() {t=new T();}
SmartPointer( const SmartPointer<T> &rhs ) {t=rhs.t;}
T& operator*() const {return(*t);}
T* operator->() const {return(t);}
SmartPointer<T>& operator= ( const SmartPointer<T> &rhs ) {t=rhs.t; return(*this);}
~SmartPointer() {delete t;}
};

The program I wrote to test this crashes, and I wouldn't be at all
surprised to learn that I've made a mistake here somewhere. And no, I
can't use Boost for this.


Yep. You copy constructor is wrong. It does a memberwise copy, when
it should do a deep copy.

SmartPointer( const SmartPointer<T> &rhs ) {t = new T( rhs.t ); }

same for your assignment operator

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #2
Karl Heinz Buchegger wrote:

Christopher Benson-Manica wrote:

Is there anything wrong with my attempt (below) at implementing
something resembling a smart pointer?

template < class T >
class SmartPointer
{
private:
T *t;

public:
SmartPointer() {t=new T();}
SmartPointer( const SmartPointer<T> &rhs ) {t=rhs.t;}
T& operator*() const {return(*t);}
T* operator->() const {return(t);}
SmartPointer<T>& operator= ( const SmartPointer<T> &rhs ) {t=rhs.t; return(*this);}
~SmartPointer() {delete t;}
};

The program I wrote to test this crashes, and I wouldn't be at all
surprised to learn that I've made a mistake here somewhere. And no, I
can't use Boost for this.


Yep. You copy constructor is wrong. It does a memberwise copy, when
it should do a deep copy.

SmartPointer( const SmartPointer<T> &rhs ) {t = new T( rhs.t ); }

same for your assignment operator


Actually the situation for the assignment operator is worse.
As it is now, it additionally leaks memory

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #3
Karl Heinz Buchegger <kb******@gascad.at> spoke thus:
Yep. You copy constructor is wrong. It does a memberwise copy, when
it should do a deep copy.
Right, right... d'oh...
SmartPointer( const SmartPointer<T> &rhs ) {t = new T( rhs.t ); }


With delete t; coming before the assignment, of course :) Thanks!

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Jul 22 '05 #4

"Christopher Benson-Manica" <at***@nospam.cyberspace.org> wrote in message
news:cn**********@chessie.cirr.com...
Is there anything wrong with my attempt (below) at implementing
something resembling a smart pointer?

template < class T >
class SmartPointer
{
private:
T *t;

public:
SmartPointer() {t=new T();}
SmartPointer( const SmartPointer<T> &rhs ) {t=rhs.t;}
T& operator*() const {return(*t);}
T* operator->() const {return(t);}
SmartPointer<T>& operator= ( const SmartPointer<T> &rhs ) {t=rhs.t;
return(*this);}
~SmartPointer() {delete t;}
};

The program I wrote to test this crashes, and I wouldn't be at all
surprised to learn that I've made a mistake here somewhere. And no, I
can't use Boost for this.


Your smart pointer is not very smart (sorry). It is basically no different
from a raw pointer. When you copy, you end up with two pointers to the same
object and no idea when it is safe to delete the pointer.

The commonest implementation of a smart pointer uses reference counting to
overcome this problem. The reference count counts how many copies of the
smart pointer you have. When the count reaches zero you know it is safe to
delete the pointer. Reference counting comes in two varieties, intrusive and
non-intrusive. With intrusive reference counting the count is held in the
pointed-to object itself, with non-intrusive the reference count is help
outside the pointed-to object.

Have a look on the web for reference counted smart pointer implementations.
Then have a look at boost, when they have high quality implementations of
both types (but a bit more complex than your typical implementation).

John
Jul 22 '05 #5
Christopher Benson-Manica wrote:

Karl Heinz Buchegger <kb******@gascad.at> spoke thus:
Yep. You copy constructor is wrong. It does a memberwise copy, when
it should do a deep copy.


Right, right... d'oh...
SmartPointer( const SmartPointer<T> &rhs ) {t = new T( rhs.t ); }


With delete t; coming before the assignment, of course :) Thanks!


Definitly not.
This is a constructor. t has no meaningful value.
Actually the whole thing should be written as

SmartPointer( const SmartPointer<T> &rhs ) : t( new T( rhs.t ) ) {}

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #6

"Karl Heinz Buchegger" <kb******@gascad.at> wrote in message
news:41**************@gascad.at...
Christopher Benson-Manica wrote:

Is there anything wrong with my attempt (below) at implementing
something resembling a smart pointer?

template < class T >
class SmartPointer
{
private:
T *t;

public:
SmartPointer() {t=new T();}
SmartPointer( const SmartPointer<T> &rhs ) {t=rhs.t;}
T& operator*() const {return(*t);}
T* operator->() const {return(t);}
SmartPointer<T>& operator= ( const SmartPointer<T> &rhs ) {t=rhs.t;
return(*this);}
~SmartPointer() {delete t;}
};

The program I wrote to test this crashes, and I wouldn't be at all
surprised to learn that I've made a mistake here somewhere. And no, I
can't use Boost for this.


Yep. You copy constructor is wrong. It does a memberwise copy, when
it should do a deep copy.

SmartPointer( const SmartPointer<T> &rhs ) {t = new T( rhs.t ); }

same for your assignment operator


A smart pointer implemented like that doesn't have many uses. Most of the
time I would prefer to simply create and copy objects than use such a smart
pointer.

john
Jul 22 '05 #7
John Harrison wrote:
[snip]
A smart pointer implemented like that doesn't have many uses. Most of the
time I would prefer to simply create and copy objects than use such a smart
pointer.


Agreed.
But if it makes the OP happy :-)
--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #8
Karl Heinz Buchegger <kb******@gascad.at> spoke thus:
This is a constructor. t has no meaningful value.
I realized that after I posted...
Actually the whole thing should be written as SmartPointer( const SmartPointer<T> &rhs ) : t( new T( rhs.t ) ) {}


That'd be nice, except that T doesn't have a copy constructor ;(

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Jul 22 '05 #9
Karl Heinz Buchegger <kb******@gascad.at> spoke thus:
But if it makes the OP happy :-)


Well, the whole exercise is necessary because I want to put some
objects in standard containers, but they don't fit in the containers
directly (thanks to their use of stupid Borland extensions).
Therefore I figured this would be the easiest way to put them in a
standard container...

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Jul 22 '05 #10
PKH
I find smartpointers to be more useful if they are integrated with the
delete-operator so that when the object the smartpointer points to is
deleted, all the smartpointers that point to it are set to point to NULL.
It's a good way to make sure you're not using pointers to deleted memory.

"Christopher Benson-Manica" <at***@nospam.cyberspace.org> wrote in message
news:cn**********@chessie.cirr.com...
Is there anything wrong with my attempt (below) at implementing
something resembling a smart pointer?

template < class T >
class SmartPointer
{
private:
T *t;

public:
SmartPointer() {t=new T();}
SmartPointer( const SmartPointer<T> &rhs ) {t=rhs.t;}
T& operator*() const {return(*t);}
T* operator->() const {return(t);}
SmartPointer<T>& operator= ( const SmartPointer<T> &rhs ) {t=rhs.t;
return(*this);}
~SmartPointer() {delete t;}
};

The program I wrote to test this crashes, and I wouldn't be at all
surprised to learn that I've made a mistake here somewhere. And no, I
can't use Boost for this.

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.

Jul 22 '05 #11

"Christopher Benson-Manica" <at***@nospam.cyberspace.org> wrote in message
news:cn**********@chessie.cirr.com...
Karl Heinz Buchegger <kb******@gascad.at> spoke thus:
This is a constructor. t has no meaningful value.


I realized that after I posted...
Actually the whole thing should be written as

SmartPointer( const SmartPointer<T> &rhs ) : t( new T( rhs.t ) ) {}


That'd be nice, except that T doesn't have a copy constructor ;(


If T doesn't have a copy ctor, then I think you should definitely be using
reference counting.

john
Jul 22 '05 #12
John Harrison <jo*************@hotmail.com> spoke thus:
If T doesn't have a copy ctor, then I think you should definitely be using
reference counting.


But the intelligence I want in the pointer is only that it knows how
to copy and delete itself :)

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Jul 22 '05 #13

"Christopher Benson-Manica" <at***@nospam.cyberspace.org> wrote in message
news:cn*********@chessie.cirr.com...
John Harrison <jo*************@hotmail.com> spoke thus:
If T doesn't have a copy ctor, then I think you should definitely be
using
reference counting.


But the intelligence I want in the pointer is only that it knows how
to copy and delete itself :)


Isn't that what reference counting gives you? I might be missing the point.

john
Jul 22 '05 #14
John Harrison <jo*************@hotmail.com> spoke thus:
Isn't that what reference counting gives you? I might be missing the point.


Well, reference counting could, I suppose, give it to me, but I don't
intend for these objects to be referred to more than once, so I'm not
sure if that's what I want. What I have seems to be working, now that
I've fixed the bugs...

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Jul 22 '05 #15

"Christopher Benson-Manica" <at***@nospam.cyberspace.org> wrote in message
news:cn*********@chessie.cirr.com...
John Harrison <jo*************@hotmail.com> spoke thus:
Isn't that what reference counting gives you? I might be missing the
point.


Well, reference counting could, I suppose, give it to me, but I don't
intend for these objects to be referred to more than once, so I'm not
sure if that's what I want. What I have seems to be working, now that
I've fixed the bugs...


If you intend to put those object into a vector, then you are going to find
it hard to avoid them being referred to more than once. For instance suppose
you vector contains four objects

v[0] is a
v[1] is b
v[2] is c
v[3] is d

Then suppose you erase b, the vector is likely to copy v[2] onto v[1], then
v[3] onto v[2] then destroy v[3]. So counting all the intermediate stages
you will get a vector that looks like this

v[0] is a
v[1] is c
v[2] is c
v[3] is d

then

v[0] is a
v[1] is c
v[2] is d
v[3] is d

then finally

v[0] is a
v[1] is c
v[2] is d

So your class must be able to deal with more than one reference at a time.
Reference counting would make copy operations like the above much more
efficient as well.

john
Jul 22 '05 #16
Here is a program that encodes and decodes a text file. What I need to do
is write a C++ program that requests 3 different file names. One filename
is for the source file to be encoded, another is the name of the 'encoded'
output file, and the final filename is an offset file. On a character by
character basis, the program needs to look at the first character of the
source file and offset it by the first character in the offset file. The
second character in the source is offset by the second character in the
secret offset file. I need to deal with the possibility that your source
is longer than the offset file in which case it just needs start over or
repeat the secret offset file from the beginning.

The one thing I am having trouble with is offsetting the source file with
the offset file. Here is my code. I need to implement the offset file. Any
ideas?
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
using namespace std;

#define cypher (char) ASCII + 1
#define decypher (char) ASCII - 1

int main()
{
char ASCII;
cout << "1) Encode\n2) Decode\n<q to quit>: ";
int coding;
cin >> coding;

if(coding == 1)
{
ifstream source;
ofstream clone;

source.open("lazy_dog.txt", ios::in);
clone.open("cypher.txt", ios::out | ios::trunc);

while(!source.eof())
{
char NewASCII;
ASCII = source.get();
if (source.fail())
return 0;
NewASCII = cypher;
clone.put(NewASCII);
}

source.close();
clone.close();
return 0;
}

else if(coding == 2)
{
ifstream origin;
ofstream copy;

origin.open("cypher.txt", ios::in);
copy.open("decypher.txt", ios::out | ios::trunc);

while(!origin.eof())
{
char NewASCII;
ASCII = origin.get();
if (origin.fail())
return 0;
NewASCII = decypher;
copy.put(NewASCII);
}

origin.close();
copy.close();
return 0;
}

else
return 0;
}
Jul 22 '05 #17
Christopher Benson-Manica wrote:

John Harrison <jo*************@hotmail.com> spoke thus:
Isn't that what reference counting gives you? I might be missing the point.


Well, reference counting could, I suppose, give it to me, but I don't
intend for these objects to be referred to more than once,


In this case you definitly should disable copying and assignment for
your pointer class.

template < class T >
class SmartPointer
{
private:
T *t;

public:
SmartPointer() {t=new T();}
T& operator*() const {return(*t);}
T* operator->() const {return(t);}
~SmartPointer() {delete t;}

private:
SmartPointer( const SmartPointer<T> &rhs ); // not implemented by intent
SmartPointer<T>& operator= ( const SmartPointer<T> &rhs ); // not implemented by intent
};

In this way it is impossible to create a copy of a SmartPointer or assign
to it, not even by accident.

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #18
Karl Heinz Buchegger wrote:

Christopher Benson-Manica wrote:

John Harrison <jo*************@hotmail.com> spoke thus:
Isn't that what reference counting gives you? I might be missing the point.


Well, reference counting could, I suppose, give it to me, but I don't
intend for these objects to be referred to more than once,


In this case you definitly should disable copying and assignment for
your pointer class.

template < class T >
class SmartPointer
{
private:
T *t;

public:
SmartPointer() {t=new T();}
T& operator*() const {return(*t);}
T* operator->() const {return(t);}
~SmartPointer() {delete t;}

private:
SmartPointer( const SmartPointer<T> &rhs ); // not implemented by intent
SmartPointer<T>& operator= ( const SmartPointer<T> &rhs ); // not implemented by intent
};

In this way it is impossible to create a copy of a SmartPointer or assign
to it, not even by accident.


I just read in another posting that you want to put those pointers into a
standard container. That will not work with the above.
I think your best bet would be to get an implementation of a reference
counted smart pointer for that task.
--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #19
Christopher Benson-Manica <at***@nospam.cyberspace.org> wrote in message news:<cn*********@chessie.cirr.com>...
John Harrison <jo*************@hotmail.com> spoke thus:
If T doesn't have a copy ctor, then I think you should definitely be using
reference counting.


But the intelligence I want in the pointer is only that it knows how
to copy and delete itself :)


Sounds like boost::shared_ptr<T>

Regards,
Michiel Salters
Jul 22 '05 #20
John Harrison <jo*************@hotmail.com> spoke thus:
If you intend to put those object into a vector, then you are going to find
it hard to avoid them being referred to more than once.
Well, unless of course I do it the stupid way I'm doing now ;) See,
with my way, I get
v[0] is a
v[1] is c
v[2] is c
v[3] is d


v[0] is a
v[1] is copy of c
v[2] is c
v[3] is d

(and so on)

It works, but I now see that it's a bad way to do it. Curse Borland
for making me have to do this in the first place ;(

I appreciate your help :)

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Jul 22 '05 #21
Karl Heinz Buchegger <kb******@gascad.at> spoke thus:
I just read in another posting that you want to put those pointers into a
standard container. That will not work with the above.


Doesn't it...? My current, perhaps bogus, understanding is that my
way works, just very inefficiently:

template < class T >
class StupidPointer
{
private:
T *t;

public:
StupidPointer() {t=new T();}
StupidPointer( const StupidPointer<T> &rhs ) {t=new T();*t=*rhs.t;}
StupidPointer<T>& operator= ( const StupidPointer<T> &rhs ) {delete t; t=new T(); *t=*rhs.t; return(*this);}
~StupidPointer() {delete t;}
};

So instead of trading references to the same object (which I now see
is the Good Way to do this), the object always gets copied. So
nothing ever gets left behind, but there are also a bunch of
unnecessary memory operations. Well, at least that's how it works in
my fantasy world...

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Jul 22 '05 #22
Christopher Benson-Manica wrote:

Karl Heinz Buchegger <kb******@gascad.at> spoke thus:
I just read in another posting that you want to put those pointers into a
standard container. That will not work with the above.


Doesn't it...?


The comment of not working has to be seen in the light of
hiding the copy constructor and assignment operator.
The standard container request your objects to be able
to perform those operations.
No copy constructor, no assignment operator -> no use in
a standard container.

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #23
Karl Heinz Buchegger <kb******@gascad.at> spoke thus:
No copy constructor, no assignment operator -> no use in
a standard container.


Well, the StupidPointer has both, right? Does it work with simple
parameters (such as int)? Or am I a StupidProgrammer? ;)

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Jul 22 '05 #24
Christopher Benson-Manica wrote:

Karl Heinz Buchegger <kb******@gascad.at> spoke thus:
No copy constructor, no assignment operator -> no use in
a standard container.


Well, the StupidPointer has both, right? Does it work with simple
parameters (such as int)? Or am I a StupidProgrammer? ;)


It is fine.

The order of events was:
* You said, that you plan to have only one pointer to the object at any time
* I suggested, in order to achieve this, to 'hide' the cctor and the op= by
making them private and not defining them. By doing this you could
*ensure* that only one pointer ever existed to the object.
To be able to ensure something is definitly better then to depend on
the programmers memory to not do it.
* Then it turned out that you want to build collections from this pointer
* In order to do this, the cctor and op= cannot be private, otherwise
you would not be able to use the containers.

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #25

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: zl2k | last post by:
hi, When I considered about preventing memory leaking, the method came up to my mind is using boost smart pointer if possible (use stl::vector instead of type, use smart pointer whenever declare...
92
by: Jim Langston | last post by:
Someone made the statement in a newsgroup that most C++ programmers use smart pointers. His actual phrase was "most of us" but I really don't think that most C++ programmers use smart pointers,...
14
by: Ian | last post by:
I am looking at porting code from a C++ application to C#. This requires implementing data sharing functionality similar to what is provided by a smart pointer in C++. I have only recently begun...
33
by: Ney André de Mello Zunino | last post by:
Hello. I have written a simple reference-counting smart pointer class template called RefCountPtr<T>. It works in conjunction with another class, ReferenceCountable, which is responsible for the...
10
by: =?iso-8859-1?q?Ernesto_Basc=F3n?= | last post by:
I am implementing my custom smart pointer: template <typename T> class MySmartPtr { public: MySmartPtr(T* aPointer) { mPointer = aPointer; }
54
by: Boris | last post by:
I had a 3 hours meeting today with some fellow programmers that are partly not convinced about using smart pointers in C++. Their main concern is a possible performance impact. I've been explaining...
3
by: alebcn75 | last post by:
Hello, I'm having a design issue that I can't solve. I'm getting from a network a stream of data, which is a http message (my program is neither a client or server, it just catches messages over...
13
by: Phil Bouchard | last post by:
I am currently writting a smart pointer which is reasonnably stable and I decided supporting allocators for completion because of its increase in efficiency when the same pool used by containers is...
50
by: Juha Nieminen | last post by:
I asked a long time ago in this group how to make a smart pointer which works with incomplete types. I got this answer (only relevant parts included): ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.