473,499 Members | 1,774 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Allocating a string buffer

Hi all,

I need to allocate a buffer large enough to store a copy of a null-terminated
string that is given to me as an argument. The code that I am using looks a lot
like old ugly C code. Is there a "better" C++ way to do this sort of thing (see
below)?

TIA - Bob

---

typedef struct ICInfo_tag {
char* Name;

// Constructor
ICInfo_tag(const char* name)
{
// Get a copy of name
size_t nameLen = strlen(name) + 1;
this->Name = static_cast<char*>(malloc(nameLen));
memcpy(this->Name, name, nameLen);
}
} ICInfo;
Jun 27 '08 #1
5 2110
Bob Altman wrote:
I need to allocate a buffer large enough to store a copy of a null-terminated
string that is given to me as an argument. The code that I am using looks a lot
like old ugly C code. Is there a "better" C++ way to do this sort of thing (see
below)?

TIA - Bob

---

typedef struct ICInfo_tag {
char* Name;

// Constructor
ICInfo_tag(const char* name)
{
// Get a copy of name
size_t nameLen = strlen(name) + 1;
this->Name = static_cast<char*>(malloc(nameLen));
memcpy(this->Name, name, nameLen);
}
} ICInfo;

The canonical safer way would be to use std::string instead of a char* so
you don't have to worry about memory in the first place. However, I assume
"ICInfo" is a struct for a good reason. If it needs to be a Plain Old
Struct, you can't use std::string (or auto_ptr<>) and there's not much room
to improve on this. If it's a struct for no good reason, then by all means
make it a class instead.

You can consider making the constructor take a const std::string& instead of
a const char*. If the rest of your code consists of good C++ citizens who
all use strings too, this is more efficient than having to use strlen() all
the time.

Of course, the one improvement you can and should make is to use new[]
instead of malloc().

--
J.
http://symbolsprose.blogspot.com
Jun 27 '08 #2
The canonical safer way would be to use std::string instead of a char* so you
don't have to worry about memory in the first place. However, I assume
"ICInfo" is a struct for a good reason.
ICInfo has a bunch of other members which I stripped out for this posting. I
simply never considered making it a class rather than a struct.

I allocate a bunch of ICInfo structures and store them in a map. Now that I
think about it, I could make ICInfo a class and the end result in my app would
be about the same.
If it needs to be a Plain Old Struct, you can't use std::string
Why not? Why can't I just say:

typedef struct ICInfo_tag {
// Use a string rather than a char*
std::string Name;
int SomeotherMember;

// Constructor
ICInfo_tag(const char* name)
{
// Get a copy of name
this->Name = name;
}
} ICInfo;
Of course, the one improvement you can and should make is to use new[] instead
of malloc().
So, instead of malloc, I would say

This->Name = new char[nameLen];

which has the advantage that it will throw an exception rather than making me
check to see if it succeeded (which my original code neglected to do)
Jun 27 '08 #3
Bob Altman wrote:
>The canonical safer way would be to use std::string instead of a char* so you
don't have to worry about memory in the first place. However, I assume
"ICInfo" is a struct for a good reason.

ICInfo has a bunch of other members which I stripped out for this posting. I
simply never considered making it a class rather than a struct.

I allocate a bunch of ICInfo structures and store them in a map. Now that I
think about it, I could make ICInfo a class and the end result in my app would
be about the same.
>If it needs to be a Plain Old Struct, you can't use std::string

Why not? Why can't I just say:

typedef struct ICInfo_tag {
// Use a string rather than a char*
std::string Name;
A Plain Old Struct (I should say Plain Old Data Structure, really) is
special in that it's "just like a C struct", i.e. no constructors, no
destructors, no class members. This is a fairly technical concept that's
sometimes necessary for interoperability (you can't hand over ICInfo structs
to C code if they contain a std::string). Not every struct is a PODS.

In your case, you don't need any of that. If you're not bound by such
restrictions, you should usually prefer std::string to char*, since it saves
you allocation headaches, and you should prefer "class" to "struct", since
the only difference in C++ is that the default access modifier for structs
is "public", whereas for classes it's "private". After adding the
appropriate modifier yourself there's no semantic difference, but it's
clearer for readers if you use "struct" only to emphasize that your class is
really not a class at all but a PODS.
int SomeotherMember;

// Constructor
ICInfo_tag(const char* name)
{
// Get a copy of name
this->Name = name;
}
Most people prefer this syntax:

ICInfo_tag(const char* name) : Name(name) { }

This is actually more efficient than your code because it directly
constructs Name instead of copying over a temporary. While that's usually a
micro-optimization that doesn't matter (though depending on the nature of
your objects, not always), C++ programmers obsess enough over
micro-optimization that most wouldn't be caught dead doing it the "slow"
way. :-)
>Of course, the one improvement you can and should make is to use new[] instead
of malloc().

So, instead of malloc, I would say

This->Name = new char[nameLen];

which has the advantage that it will throw an exception rather than making me
check to see if it succeeded (which my original code neglected to do)
There's more than that:

- You can mix malloc() and new[], but you have to make sure to call free()
or delete[] as appropriate (you can't mix up the pairings). Sticking with
new and new[] for everything is a lot less error-prone.

- new and new[] don't require casts.

- new and new[] can allocate objects. malloc() can only give you raw memory.

However, it's better still not to mess with explicitly allocated memory when
it's not necessary and use stack-allocated objects instead, relying on
destructors for cleanup. This is the well known RAII idiom (Resource
Acquisition Is Initialization, and conversely, destruction is resource
release). Plus, of course, std::string is a lot more convenient to work with
than char* if you have to do string manipulation.

--
J.
http://symbolsprose.blogspot.com
Jun 27 '08 #4
you should prefer "class" to "struct", since the only difference in C++ is
that the default access modifier for structs is "public", whereas for classes
it's "private". After adding the appropriate modifier yourself there's no
semantic difference
Ok, lets assume I've changed ICInfo into a class, and I've replaced the "char*
name" with "string name". I define my map like this:

typedef map<int, ICInfoICInfoMap;

Then, when I add an item to the map like this

g_ICInfoMap[index] = ICInfo(name, 5)

I am actually constructing a new ICInfo on the stack and then invoking the
build-in copy constructor to copy all of its member variables to a new ICInfo
contained in the map. Is that (more or less) correct? I assume that this is
something equivalent to a shallow copy. Is there anything I need to deal with
if I have a class (such as string) as a member variable?

Now, I have the following code that gets data out of the map:

void SomeSub(ICInfoMap& icInfoMap) {
// Iterate through all of the entries in the ICInfoMap
for (ICInfoMap::iterator it = icInfoMap.Begin();
it != icInfoMap.End(); it++) {
// Get a reference to the ICInfo structure
ICInfo& info = it->second;

// Do something with the ICInfo reference
cout << info.SomethingElse << endl;
}

I assume that the whole exercise of incrementing the iterator and accessing the
object via "it->second" is about as efficient as possible. In particular, I'm
hoping that I'm not causing C++ to make any more copies of the class data behind
my back. Is that correct?
Jun 27 '08 #5
If you are concerned about efficiency, consider using a vector<ICInforather than a map. You can still access elements of the
vector using an index, and the element reference is retrieved much faster.

By the way I also suggest a name other than ICInfo, such as CInfo. By convention ICInfo infers "interface belonging to the CInfo
object" which is misleading.

HTH

Brian
Jun 27 '08 #6

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

Similar topics

0
2815
by: Chris Lambacher | last post by:
Hi, I have to do some data manipulation that needs to be fast. I had a generator approach (that was faster than a list approch) which was taking approximately 5 seconds to run both encode and...
4
2794
by: Tomasz Grobelny | last post by:
Is it possible to create for example stl queue in previously allocated memory buffer (memory shared between two processes)? I thought of sth like that: queue<int>* q=new(buffer) queue<int>; but...
4
2297
by: kak3012 | last post by:
Hi, After my question today, I am not sure if this is the right group to ask but I have a simple question I guess. I have multi dimensional array called cover what I do is this iT GIVES AN...
9
7108
by: rsine | last post by:
I have developed a program that sends a command through the serial port to our business system and then reads from the buffer looking for a number. Everything worked great on my WinXP system, but...
1
6239
by: mdefoor | last post by:
I've written the following sample to split a string into chunks. Is this the right approach or is there perhaps a better way to accomplish getting chunks of a string? #include <stdio.h>...
94
4635
by: smnoff | last post by:
I have searched the internet for malloc and dynamic malloc; however, I still don't know or readily see what is general way to allocate memory to char * variable that I want to assign the substring...
3
447
by: Kane | last post by:
When you create node 1 you allocate memory and link it Again when you create node 2 you would allocate memory for that node in a different section of the code. Is there more efficient way where I...
14
2140
by: Aman JIANG | last post by:
hi i need a fast way to do lots of conversion that between string and numerical value(integer, float, double...), and boost::lexical_cast is useless, because it runs for a long time, (about 60...
10
1738
by: Chris Saunders | last post by:
Here is the declaration of a struct from WinIoCtl.h: // // Structures for FSCTL_TXFS_READ_BACKUP_INFORMATION // typedef struct _TXFS_READ_BACKUP_INFORMATION_OUT { union { //
0
7220
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
7388
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
5470
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
4919
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
3099
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
3091
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
1427
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
1
665
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
297
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

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.