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

Faster than STL string class?

P: n/a
Hi,
I learned C++ recently and I made a string class.
A code example is this:

class CString
{
public:
inline CString(const char *rhs)
{
m_size = strlen(rhs);
m_capacity = m_size * 2 + 1;
m_str = new char[m_capacity];
memmove(m_str, rhs, m_size+1);
}

inline CString& __cdecl operator+= (const CString& rhs)
{
unsigned __int32 tmp_size = m_size + rhs.m_size;

if (m_capacity <= tmp_size)
{
m_capacity = tmp_size * 2 + 1;
char *tmp_char = new char[m_capacity];
memmove(tmp_char, m_str, m_size);
delete m_str;
m_str = tmp_char;
}

memmove(m_str+m_size, rhs.m_str, rhs.m_size);
m_size = tmp_size;
return *this;
}
private:
char *m_str;
unsigned __int32 m_capacity;
unsigned __int32 m_size;
};
//stl string class
string tmp1 = "123123";
string tmp2 = "999999";
for(int i=0;i<50000;++i)
tmp1 += tmp2;
//1936033.000000 microsecond

//the "CString" class
CString tmp1 = "123123";
CString tmp2 = "999999";
for(int i=0;i<50000;++i)
tmp1 += tmp2;
//21106.333333 microsecond

Have any bug or harmful code in the "CString" class?
Why the "CString" class faster than STL string class?
Many books said that "You should not develop a class that have been developed"
In this case, Which is better?
Who can help me make a choice?

Regards,
YinTat
Jul 22 '05 #1
Share this Question
Share on Google+
23 Replies


P: n/a
YinTat wrote:
My results are different:
//stl string class
string tmp1 = "123123";
string tmp2 = "999999";
for(int i=0;i<50000;++i)
********tmp1 += tmp2;
//1936033.000000 microsecond
9780 microseconds //the "CString" class
CString tmp1 = "123123";
CString tmp2 = "999999";
for(int i=0;i<50000;++i)
tmp1 += tmp2;
//21106.333333 microsecond
4147 microseconds

I wonder why string handling is so horribly slow on your system, or was
that on some embedded system or very old PC?
Still, yours is quite a bit faster than the standard string, but the
question is how closely your "benchmark" resembles the typical use of
strings.
Have any bug or harmful code in the "CString" class?


It is not thread safe.

Jul 22 '05 #2

P: n/a
YinTat wrote:
Hi,
I learned C++ recently and I made a string class.
A code example is this:

class CString
{ [snip] }; [snip]

By the way, the Microsoft Compiler already has a class called
CString.

Should the name be changed to CppString?
A "C" string generally refers to a null terminated array
of characters; which is a string in the C language sense.

See:
http://www.jelovic.com/articles/stupid_naming.htm

Regards,
YinTat

--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.raos.demon.uk/acllc-c++/faq.html
Other sites:
http://www.josuttis.com -- C++ STL Library book

Jul 22 '05 #3

P: n/a
Rolf Magnus wrote:
YinTat wrote:
My results are different:
//stl string class
string tmp1 = "123123";
string tmp2 = "999999";
for(int i=0;i<50000;++i)
tmp1 += tmp2;
//1936033.000000 microsecond


9780 microseconds
//the "CString" class
CString tmp1 = "123123";
CString tmp2 = "999999";
for(int i=0;i<50000;++i)
tmp1 += tmp2;
//21106.333333 microsecond


4147 microseconds

I wonder why string handling is so horribly slow on your system, or was
that on some embedded system or very old PC?
Still, yours is quite a bit faster than the standard string, but the
question is how closely your "benchmark" resembles the typical use of
strings.
Have any bug or harmful code in the "CString" class?


It is not thread safe.

It appears as if the std::string class from the OP suffers from a O(n^2)
flaw that was hurting, e.g., some older version of MFC CString
implementations. This has been fixed, though.

On my machine the handcoded CString class beats std::string but not by a
factor of 2. However, it should be pointed out, that there is an obvious
parameter in the speed-space tradeoff: CString doubles the allocated
memory. It would surely waste less memory at the cost of more allocations
if that factor was decreased. Similarly, one could still speed it up by
increasing that factor.

Moreover, on many implementations, std::string is trying to be smart about
assignments. In reference count based implementations, many times an
assignment of strings will result in only little more than a pointer copy.
Thus, which implementation is better for a given project is very hard to
predict. In any case, I would doubt that the gain is worth the effort of
actually coding a complete string class. Well, unless of course std::string
completely sucks as appears to be the case with the OP.
Best

Kai-Uwe
Jul 22 '05 #4

P: n/a
> It is not thread safe.

Silly question: why? I don't get all this thread safe, multithreading
things. Can anyone explain it briefly?
-Gernot
Jul 22 '05 #5

P: n/a
YinTat wrote:
I learned C++ recently and I made a string class.
A code example is this:

class CString
{
public:
inline CString(const char *rhs)
{
m_size = strlen(rhs);
m_capacity = m_size * 2 + 1;
m_str = new char[m_capacity];
memmove(m_str, rhs, m_size+1);
}

inline CString& __cdecl operator+= (const CString& rhs)
{
unsigned __int32 tmp_size = m_size + rhs.m_size;

if (m_capacity <= tmp_size)
{
m_capacity = tmp_size * 2 + 1;
char *tmp_char = new char[m_capacity];
memmove(tmp_char, m_str, m_size);
delete m_str;
delete[] m_str;
m_str = tmp_char;
}

memmove(m_str+m_size, rhs.m_str, rhs.m_size);
m_size = tmp_size;
return *this;
}
private:
char *m_str;
unsigned __int32 m_capacity;
unsigned __int32 m_size;
};
//stl string class
string tmp1 = "123123";
string tmp2 = "999999";
for(int i=0;i<50000;++i)
tmp1 += tmp2;
//1936033.000000 microsecond

//the "CString" class
CString tmp1 = "123123";
CString tmp2 = "999999";
for(int i=0;i<50000;++i)
tmp1 += tmp2;
//21106.333333 microsecond

Have any bug or harmful code in the "CString" class?
Well, it's not supposed to compile with a conforming compiler because
__cdecl and __int32 are not defined. I presume they are something
like
#define __cdecl
and
typedef long __int32;
in reality.

As to the bugs, yes, most definitely. First, see above. You use
'delete' where you supposed to use 'delete[]'. Second, your class
has a memory leak: the allocated memory is never released if the
string doesn't have to grow, and even then, the first one is freed
when the second allocated, but there is always one array that is
never released at the end. It may be acceptable to you, but it's
definitely unacceptable in a standard library implementation.
Why the "CString" class faster than STL string class?
Because it has very little functionality and is buggy. Analogy:
a race car can go faster than a production car or go over a rougher
terrain, but it can never compare with the production car in comfort,
universality, gas mileage, etc.

Remove all the glass from your car, remove the spare tire, drop the
back seat, the passenger seat, reduce the gas tank to one gallon,
replace the hood, the quarter-panels, door panes, with plastic, and
you will have something that drives faster than it did before all
the modifications. Is it better? Depends on how you look at it.
Many books said that "You should not develop a class that have been developed"
In this case, Which is better?
Better is the one that is bug-free. Once you make your class bug-
free, your class can still be better in some applications (i.e. for
doing what you need it to do), but it can never be as suitable for
being in a library as the one in the library.
Who can help me make a choice?


Wise people that write books can. If you don't listen to them, or
to those who give you advice elsewhere, how can they help you make
your choice?

Some folks I've known have developed their own custom string types
for very specific purposes. Those string classes are fast and slim
but can only be used in a very limited set of conditions. The string
class in the Standard Library is designed with a different purpose.
It's generic, it's conforming to requirements to standard containers,
it's stable, and it's portable. If you don't like it, or if you have
other requirements (fewer, less strict, whatever), and you have enough
time to spare, do design your own, by all means. Just please do not
put such class in an application running on a life support machine to
which I'm going to be hooked up after a major surgery.

V
Jul 22 '05 #6

P: n/a
Gernot Frisch wrote:
It is not thread safe.


Silly question: why? I don't get all this thread safe, multithreading
things. Can anyone explain it briefly?
-Gernot


In the context of the C++ language, it doesn't matter and is actually
off-topic.

Unless you are using operating-system specific calls, a C++ program has no
notion of threads, multi-threadedness, etc. and doesn't need to be considered
when writing code.

If you are using threads, then you need to refer to the specifics of that
implementation as to how it affects the C++ libraries.

In short, you don't need to worry about it unless you specifically use threads.

However, in answer to your question: thread-safe describes some construct,
class, etc. that is specifically protected against corruption if two (or more)
threads try to access that object at the same time. For example, suppose you
have one string 'str' and two threads and perform the following:

//thread 1
str = "hello from Earth";

// thread 2
str = "greetings to all inhabitants of Mars";

If both were executed simultaneously, what would be the outcome? If str isn't
thread-safe, corruption would be inevitable. If str is thread-safe, then
typically the first thread to write would be granted exclusive write-access
until the assignment is completed, and the second thread would block until the
first is done, and then would gain exclusive write access.

Books are devoted to the subject, this is a trivial example, but should serve
to answer your question.
Jul 22 '05 #7

P: n/a
pr******@hotmail.com (YinTat) wrote in message news:<4c**************************@posting.google. com>...
class CString
{
public:
inline CString(const char *rhs)
{
m_size = strlen(rhs);
m_capacity = m_size * 2 + 1;
m_str = new char[m_capacity];
memmove(m_str, rhs, m_size+1);
}

inline CString& __cdecl operator+= (const CString& rhs)
{
unsigned __int32 tmp_size = m_size + rhs.m_size;

if (m_capacity <= tmp_size)
{
m_capacity = tmp_size * 2 + 1;
char *tmp_char = new char[m_capacity];
memmove(tmp_char, m_str, m_size);
delete m_str;
m_str = tmp_char;
}

memmove(m_str+m_size, rhs.m_str, rhs.m_size);
m_size = tmp_size;
return *this;
}
private:
char *m_str;
unsigned __int32 m_capacity;
unsigned __int32 m_size;
};

Have any bug or harmful code in the "CString" class?


I see two problems with this code:

1) No destructor.
2) Not exception safe. If new throws in operator+=, m_capacity will have
a larger value then the actual capacity. If you call operator+= after
catching an exception, the code can write to memory it does not own.]

samuel
Jul 22 '05 #8

P: n/a
"YinTat" <pr******@hotmail.com> wrote in message
news:4c**************************@posting.google.c om...
Have any bug or harmful code in the "CString" class?
Why the "CString" class faster than STL string class?


Besides the problems already mentioned, you are missing a destructor, copy
constructor and copy assignment.

Regards,
Martin
Jul 22 '05 #9

P: n/a
In article <4c**************************@posting.google.com >,
pr******@hotmail.com (YinTat) wrote:
Hi,
I learned C++ recently and I made a string class.
I would respectfully suggest that someone who recently learned C++, may
not be the best person to decide that they can write a better string
class than multi-year professionals.

A code example is this:

class CString
{
public:
inline CString(const char *rhs)
{
m_size = strlen(rhs);
m_capacity = m_size * 2 + 1;
Why are you adding one here?
m_str = new char[m_capacity];
memmove(m_str, rhs, m_size+1);
I see that you are copying the null into m_str here...
}
You need a copy c_tor and d_tor or everytime you are done using a
CString, you will be leaking memory, and everytime you copy one CString
to another, you will be both leaking memory and making it impossible for
the two CString objects to work properly.

inline CString& __cdecl operator+= (const CString& rhs)
{
unsigned __int32 tmp_size = m_size + rhs.m_size;

if (m_capacity <= tmp_size)
{
m_capacity = tmp_size * 2 + 1;
Again, your adding one. Why?
char *tmp_char = new char[m_capacity];
If new throws, m_capacity will equal the wrong value.
memmove(tmp_char, m_str, m_size);
delete m_str;
That's delete [] m_str;
m_str = tmp_char;
}

memmove(m_str+m_size, rhs.m_str, rhs.m_size);
Here you don't copy the null into m_str like you did above. Why?
m_size = tmp_size;
return *this;
}
private:
char *m_str;
unsigned __int32 m_capacity;
unsigned __int32 m_size;
}; Have any bug or harmful code in the "CString" class?
CString s1( "hello" );
CString s2( "world" );
s1 = s2;
s1 += s1;
// now look at the contents of s2...

while (true) {
CString s1( "abcdefghijklmnopqrstuvwxyz" );
}

While the above is running track your programs memory usage...

Why the "CString" class faster than STL string class?
Because your CString class doesn't do everything std::string does. Your
CString class is designed more like a std::vector<char>. Compare your
CString to that and see what happens. (Make sure you are compiling in
debug mode when you do this.)

Many books said that "You should not develop a class that have been developed"
Why do you think they say that?

In this case, Which is better?


(1) The one that works.
(2) If (and only if) they both work, then use the one that is more
efficient for the task at hand. In some cases a class like yours (that
routenly holds twice as much memory as needed,) would be a very bad
choice; in some cases any class that requires the memory be contigious
would be a bad choice. Use the one that best solves your particular
problem.
You may very well be able to implement a better string class than the
one that comes with your library. If you can, then more power to you!
Implementing std::string is one of the many worthy projects for a
beginner learning the language (though implementing std::vector would be
easier.)
Jul 22 '05 #10

P: n/a

"Ron Samuel Klatchko" <mo*********@yahoo.com> wrote in message
I see two problems with this code:

1) No destructor.
2) Not exception safe. If new throws in operator+=, m_capacity will have
a larger value then the actual capacity. If you call operator+= after
catching an exception, the code can write to memory it does not own.]


Right, I have found that calls to delete and delete[] are often quite
expensive.

You can often gain strong exception safety by rearranging code, rather than
by using try-catch blocks.
Jul 22 '05 #11

P: n/a

"YinTat" <pr******@hotmail.com> wrote in message
news:4c**************************@posting.google.c om...
Hi,
I learned C++ recently and I made a string class.
In addition to others in this thread, I can add some comments.
A code example is this:

class CString
{
public:
inline CString(const char *rhs)
{
m_size = strlen(rhs);
m_capacity = m_size * 2 + 1;
m_str = new char[m_capacity];
memmove(m_str, rhs, m_size+1);
Here you copy terminating zero into CString.
}

inline CString& __cdecl operator+= (const CString& rhs)
{
unsigned __int32 tmp_size = m_size + rhs.m_size;

if (m_capacity <= tmp_size)
{
m_capacity = tmp_size * 2 + 1;
char *tmp_char = new char[m_capacity];
memmove(tmp_char, m_str, m_size);
delete m_str;
m_str = tmp_char;
}

memmove(m_str+m_size, rhs.m_str, rhs.m_size);
m_size = tmp_size;
return *this;
}

no terminating zero in this case
Why the "CString" class faster than STL string class?

Not on my system:)
I think that's probably because of allocation strategy.
int main()
{
clock_t start = clock();
//stl string class
string tmp1;
tmp1.reserve(500001*6);
tmp1 = "123123";
string tmp2 = "999999";
for(int i=0;i<500000;++i)
{
tmp1 += tmp2;
}
clock_t end = clock();
cout<<"string:"<<(end-start)<<'\n';
//1936033.000000 microsecond

//the "CString" class
start = clock();
CString ctmp1 = "123123";
CString ctmp2 = "999999";
for(int i=0;i<500000;++i)
{
ctmp1 += ctmp2;
}
end = clock();
cout<<"cstring:"<<(end-start)<<'\n';
//21106.333333 microsecond

}

[bmaxa@localhost bmaxa]$ g++ -O3 -Wall faster.cc -o faster
[bmaxa@localhost bmaxa]$ ./faster
string:50000
cstring:40000
[bmaxa@localhost bmaxa]$ ./faster
string:50000
cstring:50000
[bmaxa@localhost bmaxa]$ ./faster
string:50000
cstring:40000
[bmaxa@localhost bmaxa]$ ./faster
string:40000
cstring:40000
[bmaxa@localhost bmaxa]$ ./faster
string:50000
cstring:40000
[bmaxa@localhost bmaxa]$ ./faster
string:50000
cstring:40000
[bmaxa@localhost bmaxa]$ ./faster
string:50000
cstring:50000
[bmaxa@localhost bmaxa]$ ./faster
string:50000
cstring:40000
[bmaxa@localhost bmaxa]$ ./faster
string:50000
cstring:40000
[bmaxa@localhost bmaxa]$ ./faster
string:40000
cstring:50000
Greets, Bane.
Jul 22 '05 #12

P: n/a
"Martin M. Pedersen" <noname> wrote in message news:<40*********************@dread11.news.tele.dk >...
"YinTat" <pr******@hotmail.com> wrote in message
news:4c**************************@posting.google.c om...
Have any bug or harmful code in the "CString" class?
Why the "CString" class faster than STL string class?


Besides the problems already mentioned, you are missing a destructor, copy
constructor and copy assignment.

Regards,
Martin


#pragma once

#include <cstring>
/************************************Class********* ****************************/
class CString
{
public:
/***********************Construction/Destruction***************************/
inline CString():m_capacity(1), m_size(0)
{
m_str = new char[1];
}

inline CString(const CString& rhs)
{
m_size = rhs.m_size;
m_capacity = rhs.m_capacity;
m_str = new char[m_capacity];
memmove(m_str, rhs.m_str, m_size+1);
}

inline CString(const char *rhs)
{
m_size = strlen(rhs);
m_capacity = m_size * 2 + 1;
m_str = new char[m_capacity];
memmove(m_str, rhs, m_size+1);
}

inline ~CString()
{
delete[] m_str;
}
/*******************************Operator*********** ************************/
inline CString& operator= (const CString& rhs)
{
if (this == &rhs)
return *this;

m_size = rhs.m_size;

if (m_capacity <= m_size)
{
m_capacity = rhs.m_capacity;
delete[] m_str;
m_str = new char[m_capacity];
}

memmove(m_str, rhs.m_str, m_size+1);
return *this;
}

inline CString& operator= (const char *rhs)
{
if (m_str == rhs)
return *this;

m_size = strlen(rhs);

if (m_capacity <= m_size)
{
m_capacity = m_size * 2 + 1;
delete[] m_str;
m_str = new char[m_capacity];
}

memmove(m_str, rhs, m_size+1);
return *this;
}

inline bool operator== (const CString& rhs)
{
if (m_size == rhs.m_size)
return (memcmp(m_str, rhs.m_str, m_size)==0);
else
return false;
}

inline bool operator== (const char *rhs)
{
return (memcmp(m_str, rhs, m_size)==0);
}

inline CString& operator+= (const CString& rhs)
{
unsigned int tmp_size = m_size + rhs.m_size;

if (m_capacity <= tmp_size)
{
m_capacity = tmp_size * 2 + 1;
char *tmp_char = new char[m_capacity];
memmove(tmp_char, m_str, m_size);
delete[] m_str;
m_str = tmp_char;
}

memmove(m_str+m_size, rhs.m_str, rhs.m_size);
m_size = tmp_size;
return *this;
}

inline CString& operator+= (const char *rhs)
{
unsigned int rhs_size = strlen(rhs);
unsigned int tmp_size = m_size + rhs_size;

if (m_capacity <= tmp_size)
{
m_capacity = tmp_size * 2 + 1;
char *tmp_char = new char[m_capacity];
memmove(tmp_char, m_str, m_size);
delete[] m_str;
m_str = tmp_char;
}

memmove(m_str+m_size, rhs, rhs_size);
m_size = tmp_size;
return *this;
}

inline CString* operator& ()
{
return this;
}

inline const CString* operator& () const
{
return this;
}
/****************************Class
Function********************************/
//"123456789".size = "123456789"
inline const char* c_str()
{
return m_str;
}
//"123456789".size = 9
inline unsigned int size()
{
return m_size;
}
//"123456789".clearmem = ""
inline CString& clearmem()
{
delete[] m_str;
m_str = new char[1];
m_capacity = 1;
m_size = 0;
return *this;
}
//"123456789".insert(3,"xxx")="123xxx456789"
inline CString& insert(unsigned int pos, const char *rhs)
{
unsigned int rhs_size = strlen(rhs);
unsigned int tmp_size = m_size + rhs_size;

if (m_capacity <= tmp_size)
{
m_capacity = tmp_size * 2 + 1;
char *tmp_char = new char[m_capacity];
memmove(tmp_char, m_str, pos);
memmove(tmp_char+pos+rhs_size, m_str+pos, m_size-pos+1); //1 for
'/0'
delete[] m_str;
m_str = tmp_char;
}
else
{
memmove(m_str+pos+rhs_size, m_str+pos, m_size-pos+1);
}

memmove(m_str+pos, rhs, rhs_size);
m_size = tmp_size;
return *this;
}
//"123456789".insert(3,"xxx")="123xxx456789"
inline CString& insert(unsigned int pos, const CString& rhs)
{
unsigned int tmp_size = m_size + rhs.m_size;

if (m_capacity <= tmp_size)
{
m_capacity = tmp_size * 2 + 1;
char *tmp_char = new char[m_capacity];
memmove(tmp_char, m_str, pos);
memmove(tmp_char+pos+rhs.m_size, m_str+pos, m_size-pos+1);//1 for
'/0'
delete[] m_str;
m_str = tmp_char;
}
else
{
memmove(m_str+pos+rhs.m_size, m_str+pos, m_size-pos+1);
}

memmove(m_str+pos, rhs.m_str, rhs.m_size);
m_size = tmp_size;
return *this;
}
//"123456789".erase(3,3)="123789"
inline CString& erase(unsigned int pos, unsigned int len)
{
memmove(m_str+pos, m_str+pos+len, m_size-pos+1);
m_size = m_size - len;
return *this;
}
//"123456789".assign(3,3)="456"
inline CString& assign(unsigned int pos, unsigned int len)
{
memmove(m_str, m_str+pos, len);
m_str[len] = '\0';
m_size = len;
return *this;
}
//"123456789".fill(5,'1') = "11111"
inline CString& fill(unsigned int len, char fillch)
{
if (m_capacity <= m_size)
{
m_capacity = len * 2 + 1;
delete[] m_str;
m_str = new char[m_capacity];
}
memset(m_str, fillch, len);
m_str[len] = '0';
return *this;

}
//"123456789".replace(3,3,"xxxxxx") = "123xxxxxx789"
inline CString& replace(unsigned int pos, unsigned int len,
const char *rhs)
{
if ((pos + len) > m_size)
throw 0xC000008CL;
unsigned int rhs_size = strlen(rhs);
unsigned int tmp_size = m_size + rhs_size - len;

if (len != rhs_size)
{
if (m_capacity <= tmp_size)
{
m_capacity = tmp_size * 2 + 1;
char *tmp_char = new char[m_capacity];
memmove(tmp_char, m_str, pos);
memmove(tmp_char+pos+rhs_size, m_str+pos+len,
tmp_size-pos-rhs_size+1); //1 for '/0'
delete[] m_str;
m_str = tmp_char;
}
else
{
memmove(m_str+pos+rhs_size, m_str+pos+len,
tmp_size-pos-rhs_size+1); //1 for '/0'
}
}

memmove(m_str+pos, rhs, rhs_size);
m_size = tmp_size;
return *this;
}
//"123456789".replace(3,3,"xxxxxx") = "123xxxxxx789"
inline CString& replace(unsigned int pos, unsigned int len,
CString& rhs)
{
if ((pos + len) > m_size)
throw 0xC000008CL;
unsigned int tmp_size = m_size + rhs.m_size - len;

if (len != rhs.m_size)
{
if (m_capacity <= tmp_size)
{
m_capacity = tmp_size * 2 + 1;
char *tmp_char = new char[m_capacity];
memmove(tmp_char, m_str, pos);
memmove(tmp_char+pos+rhs.m_size, m_str+pos+len,
tmp_size-pos-rhs.m_size+1); //1 for '/0'
delete[] m_str;
m_str = tmp_char;
}
else
{
memmove(m_str+pos+rhs.m_size, m_str+pos+len,
tmp_size-pos-rhs.m_size+1); //1 for '/0'
}
}

memmove(m_str+pos, rhs.m_str, rhs.m_size);
m_size = tmp_size;
return *this;
}
private:
char *m_str;
unsigned int m_capacity;
unsigned int m_size;
};
Jul 22 '05 #13

P: n/a
In article <ca*************@news.t-online.com>,
Rolf Magnus <ra******@t-online.de> wrote:
Have any bug or harmful code in the "CString" class?


It is not thread safe.


I don't see what makes the OP's CString less thread safe than
std::string. Can you clarify ?
Jul 22 '05 #14

P: n/a
Mats Weber wrote:
In article <ca*************@news.t-online.com>,
Rolf Magnus <ra******@t-online.de> wrote:
Have any bug or harmful code in the "CString" class?


It is not thread safe.


I don't see what makes the OP's CString less thread safe than
std::string. Can you clarify ?


For std::string, it depends on the implementation. The OP's
implemenatation of his class definitely isn't thread safe.

Jul 22 '05 #15

P: n/a

"Mats Weber" <ma***@bluewin.ch> wrote in message
news:ma*************************@sicinfo.epfl.ch.. .
In article <ca*************@news.t-online.com>,
Rolf Magnus <ra******@t-online.de> wrote:
Have any bug or harmful code in the "CString" class?


It is not thread safe.


I don't see what makes the OP's CString less thread safe than
std::string. Can you clarify ?


The m_capacity member is updated before new char[...]. If the new operator
throws an exception the CString object is left in an invalid state;
m_capacity member holds a value that does not reflect the actual size of
the allocated buffer.

--
Peter van Merkerk
peter.van.merkerk(at)dse.nl
Jul 22 '05 #16

P: n/a
Peter van Merkerk wrote:

"Mats Weber" <ma***@bluewin.ch> wrote in message
news:ma*************************@sicinfo.epfl.ch.. .
In article <ca*************@news.t-online.com>,
Rolf Magnus <ra******@t-online.de> wrote:
> Have any bug or harmful code in the "CString" class?

It is not thread safe.


I don't see what makes the OP's CString less thread safe than
std::string. Can you clarify ?


The m_capacity member is updated before new char[...]. If the new operator
throws an exception the CString object is left in an invalid state;
m_capacity member holds a value that does not reflect the actual size of
the allocated buffer.

--
Peter van Merkerk
peter.van.merkerk(at)dse.nl


You are talking about exception safe, which has nothing to do w/ threads or
thread-safe.
Jul 22 '05 #17

P: n/a
In article <2j************@uni-berlin.de>,
"Peter van Merkerk" <me*****@deadspam.com> wrote:
The m_capacity member is updated before new char[...]. If the new operator
throws an exception the CString object is left in an invalid state;
m_capacity member holds a value that does not reflect the actual size of
the allocated buffer.


That is exception safety, not thread safety.
Jul 22 '05 #18

P: n/a
In article <ca*************@news.t-online.com>,
Rolf Magnus <ra******@t-online.de> wrote:
For std::string, it depends on the implementation. The OP's
implemenatation of his class definitely isn't thread safe.


You really have to define what you mean by thread safe for a string
handling package. If you mean that two threads should be able to
concurrently access the same string object, then I think no reasonable
implementation of std::string will do that because the overhead would be
HUGE.

If you just mean that distinct strings can be manipulated concurrently,
then the OP's implementation is just fine because it has no global
variable. The only global resource is memory, and thread safe versions
of new/delete are used in a threaded program.
Jul 22 '05 #19

P: n/a
> I would respectfully suggest that someone who recently learned C++, may
not be the best person to decide that they can write a better string
class than multi-year professionals. So I very worry that I will regret...
A code example is this:

class CString
{
public:
inline CString(const char *rhs)
{
m_size = strlen(rhs);
m_capacity = m_size * 2 + 1;
Why are you adding one here?

I also don't know why I adding one here...
I adding one here by "intuition" =="
m_str = new char[m_capacity];
memmove(m_str, rhs, m_size+1);
I see that you are copying the null into m_str here...
}


You need a copy c_tor and d_tor or everytime you are done using a
CString, you will be leaking memory, and everytime you copy one CString
to another, you will be both leaking memory and making it impossible for
the two CString objects to work properly.

inline CString& __cdecl operator+= (const CString& rhs)
{
unsigned __int32 tmp_size = m_size + rhs.m_size;

if (m_capacity <= tmp_size)
{
m_capacity = tmp_size * 2 + 1;


Again, your adding one. Why?
char *tmp_char = new char[m_capacity];


If new throws, m_capacity will equal the wrong value.
memmove(tmp_char, m_str, m_size);
delete m_str;


That's delete [] m_str;

In destruction, I use "delete [] m_str;"....
but I forget adding "[]" in here...
thanks!
m_str = tmp_char;
}

memmove(m_str+m_size, rhs.m_str, rhs.m_size);
Here you don't copy the null into m_str like you did above. Why?

I forget once again.....
Thanks..
I have no remembrance and experience.
m_size = tmp_size;
return *this;
}
private:
char *m_str;
unsigned __int32 m_capacity;
unsigned __int32 m_size;
};
Have any bug or harmful code in the "CString" class?


CString s1( "hello" );
CString s2( "world" );
s1 = s2;
s1 += s1;
// now look at the contents of s2...

while (true) {
CString s1( "abcdefghijklmnopqrstuvwxyz" );
}

While the above is running track your programs memory usage...

Why the "CString" class faster than STL string class?


Because your CString class doesn't do everything std::string does. Your
CString class is designed more like a std::vector<char>. Compare your
CString to that and see what happens. (Make sure you are compiling in
debug mode when you do this.)

But in my compiler(VC++6) std::string is designed like a
std::vector<char>.
(doubles the allocated memory)
So I was disorientated....
Many books said that "You should not develop a class that have been developed"
Why do you think they say that?

In this case, Which is better?


(1) The one that works.
(2) If (and only if) they both work, then use the one that is more
efficient for the task at hand. In some cases a class like yours (that
routenly holds twice as much memory as needed,) would be a very bad
choice; in some cases any class that requires the memory be contigious
would be a bad choice. Use the one that best solves your particular
problem.

My case is a ISAPI extension, and therefore I very attach importance
to string class.
You may very well be able to implement a better string class than the
one that comes with your library. If you can, then more power to you!
Implementing std::string is one of the many worthy projects for a
beginner learning the language (though implementing std::vector would be
easier.)

So, I am making std::vector,std::list,std::vector_list,std::except ion
and database class.
Has Anything else good for beginner?
Jul 22 '05 #20

P: n/a
"Mats Weber" <ma***@bluewin.ch> wrote in message
news:ma*************************@sicinfo.epfl.ch.. .
In article <ca*************@news.t-online.com>,
Rolf Magnus <ra******@t-online.de> wrote:
For std::string, it depends on the implementation. The OP's
implemenatation of his class definitely isn't thread safe.


You really have to define what you mean by thread safe for a string
handling package. If you mean that two threads should be able to
concurrently access the same string object, then I think no reasonable
implementation of std::string will do that because the overhead would be
HUGE.

If you just mean that distinct strings can be manipulated concurrently,
then the OP's implementation is just fine because it has no global
variable. The only global resource is memory, and thread safe versions
of new/delete are used in a threaded program.


Microsoft claims to provide a truly thread-safe version for
multithreaded applications of the string class, if I am not mistaken.

regards
--
jb

(replace y with x if you want to reply by e-mail)
Jul 22 '05 #21

P: n/a
Jakob Bieling wrote:
"Mats Weber" <ma***@bluewin.ch> wrote in message
news:ma*************************@sicinfo.epfl.ch.. .
In article <ca*************@news.t-online.com>,
Rolf Magnus <ra******@t-online.de> wrote:
>For std::string, it depends on the implementation. The OP's
>implemenatation of his class definitely isn't thread safe.


You really have to define what you mean by thread safe for a string
handling package. If you mean that two threads should be able to
concurrently access the same string object, then I think no reasonable
implementation of std::string will do that because the overhead would be
HUGE.

If you just mean that distinct strings can be manipulated concurrently,
then the OP's implementation is just fine because it has no global
variable. The only global resource is memory, and thread safe versions
of new/delete are used in a threaded program.


Microsoft claims to provide a truly thread-safe version for
multithreaded applications of the string class, if I am not mistaken.

regards


What does "truly thread safe" mean? At most it means that all string
operations are atomic. Now, that is usually not even useful: if two threads
use modifying operations on the same string, none of them can make
reasonable predictions about the contents unless they lock the string for
some times and release the string once it is no longer necessary to know
about its contents.

There is a very well reasoned treatment about what thread safety could and
should mean for container classes on the SGI website for their (outdated)
reference implementation of the STL.

http://www.sgi.com/tech/stl/thread_safety.html

From there:
<quote>
The SGI implementation of STL is thread-safe only in the sense that
simultaneous accesses to distinct containers are safe, and simultaneous
read accesses to to shared containers are safe. If multiple threads access
a single container, and at least one thread may potentially write, then the
user is responsible for ensuring mutual exclusion between the threads
during the container accesses.
</quote>

This kind of thread safety is more or less automatic one you do not use
static variables in your container class.

Now, I would like to know how Microsoft differs.
Best

Kai-Uwe
Jul 22 '05 #22

P: n/a
"Kai-Uwe Bux" <jk********@gmx.net> wrote in message
news:ca**********@news01.cit.cornell.edu...
Jakob Bieling wrote:
"Mats Weber" <ma***@bluewin.ch> wrote in message
news:ma*************************@sicinfo.epfl.ch.. .
In article <ca*************@news.t-online.com>,
Rolf Magnus <ra******@t-online.de> wrote:

>For std::string, it depends on the implementation. The OP's
>implemenatation of his class definitely isn't thread safe.

You really have to define what you mean by thread safe for a string
handling package. If you mean that two threads should be able to
concurrently access the same string object, then I think no reasonable
implementation of std::string will do that because the overhead would be HUGE.

If you just mean that distinct strings can be manipulated concurrently,
then the OP's implementation is just fine because it has no global
variable. The only global resource is memory, and thread safe versions
of new/delete are used in a threaded program.
Microsoft claims to provide a truly thread-safe version for
multithreaded applications of the string class, if I am not mistaken.

regards


What does "truly thread safe" mean? At most it means that all string
operations are atomic. Now, that is usually not even useful: if two

threads

Yes, this is what I meant.
use modifying operations on the same string, none of them can make
reasonable predictions about the contents unless they lock the string for
some times and release the string once it is no longer necessary to know
about its contents.

There is a very well reasoned treatment about what thread safety could and
should mean for container classes on the SGI website for their (outdated)
reference implementation of the STL.

http://www.sgi.com/tech/stl/thread_safety.html

From there:
<quote>
The SGI implementation of STL is thread-safe only in the sense that
simultaneous accesses to distinct containers are safe, and simultaneous
read accesses to to shared containers are safe. If multiple threads access
a single container, and at least one thread may potentially write, then the user is responsible for ensuring mutual exclusion between the threads
during the container accesses.
</quote>

This kind of thread safety is more or less automatic one you do not use
static variables in your container class.

Now, I would like to know how Microsoft differs.


I only read that using the multithreaded library also gives you a
thread-safe string version (I assume this applies not only the std::string,
but to any other container as well). To me, that would mean that
stimultanious write accesses are also synchronized. Basically what you said
above. But I might be misinterpreting something. I also found the article my
initial statement was based on:
http://support.microsoft.com/default...b;en-us;813810

regards
--
jb

(replace y with x if you want to reply by e-mail)
Jul 22 '05 #23

P: n/a

"Mats Weber" <ma***@bluewin.ch> wrote in message
news:ma*************************@sicinfo.epfl.ch.. .
In article <2j************@uni-berlin.de>,
"Peter van Merkerk" <me*****@deadspam.com> wrote:
The m_capacity member is updated before new char[...]. If the new operatorthrows an exception the CString object is left in an invalid state;
m_capacity member holds a value that does not reflect the actual size of
the allocated buffer.


That is exception safety, not thread safety.


Whoops, my mistake...I should learn to read next time...
Jul 22 '05 #24

This discussion thread is closed

Replies have been disabled for this discussion.