String objects allocations

Let's run this code.



1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include <vector>
#include <string>

int main()
{
std::string* p_array = new std::string[10];//Creates 10 elements of String
std::string parr[10];
return 0;
}


The first line does:
I allocated 10 objects of class String from STL library. Now I can separately manipulate every object using member functions of String class. These 10 objects are initialized to Empty string ("").

The second line does:
I allocated 10 objects of class String from STL library and created a pointer to the first object of class String. These 10 objects are initialized to Empty string.

I hope it is correct.
But I don't understand the difference between these 2 definitions / allocations of 10 std::string objects.
Or these 2 lines are identical and it means no difference between them.

Can anyone help me?
Thank you in advance.
Last edited on
p_array declares an array for strings on the heap. You'll need to delete them when you're done to destroy the array and the elements. p_array is just a pointer to the first element of the array.

parr declares an array of strings on the stack. parr is the actuall array. When the function terminates, the array and the strings are destroyed.
Thank you, kbw.

You mean that p_array objects I must delete in my code. But parr objects will be deleted by OS.
Am I right? If so, should I allocate string objects using just the second declaration?
What are the advantages to use the first declaration?
Last edited on
I think I need to highlight what I want to know.
I found everything about Heap and Stack in Internet and the forum.

But all those advantages and disadvantages also concern to objects of STL or boost libraries?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <vector>
#include <string>

int main()
{
    {
        std::string* p_array = new std::string[10]; // on the free store (heap)
    } // oops! memory leak

    {
        std::string parr[10]; // on the stack
    } // no leak
    return 0;
}


You need to delete[] p_array; before it goes out of scope or otherwise becomes unreachable.

Here are some (not an exhaustive list...) points about each. First, the array on the free store:
- Has to be explicitly deleted[]
- Is not exception safe
- Can be passed around, cross scope boundaries, etc.
- Is created at run-time and it's size (10) can be a run-time variable

Now, the array on the stack:
- Automatically cleaned up
- Therefore, exception safe
- Is local to the scope
- Must be a compile-time constant size

Thank you, moorecm.

Let's change this code and now we will use boost::shared_ptr instead of the raw pointer to std::string. I see boost::shared_ptr be the best for this case:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <vector>
#include <string>

int main()
{
    {
        shared_ptr<std::string> p_array(new std::string[10]); // on the free store (heap)
        //std::string* p_array = new std::string[10]; // on the free store (heap)

    }    // No any memory leak. 
         // Is it correct?

    {
        std::string parr[10]; // on the stack
    } // no leak
    return 0;
}



1)So now, when we use boost::shared_ptr, the program has no memory leak.
Is it correct?

2)Next: boost::shared_ptr is the best for this case.
Is it correct?

Thanks in advance.
Actually, I'm not sure about this usage. I would guess that the implementation of shared_ptr is specialized for arrays somehow, but I can't confirm without checking some documentation.

The concern is that you have to use delete[] not delete on an array allocated with new[]. For example, std::auto_ptr should never be used with arrays because it calls delete when it goes out of scope.


EDIT: A quick Google search confirms the concern. Do not use shared_ptr, use shared_array--then you're good.
http://www.boost.org/doc/libs/1_46_0/libs/smart_ptr/shared_array.htm
Last edited on
Thank you, moorecm.
I will try with boost::shared_array.
1)So now, when we use boost::shared_ptr, the program has no memory leak.
Is it correct?
Yes. Actually, a boost::shared_ptr is a "referenced counted" thing so has facilities that you're not using. But yes, in your example, it does delete the array.

2)Next: boost::shared_ptr is the best for this case.
Is it correct?
No. You could use std::auto_ptr or boost::scoped_array.

http://www.boost.org/doc/libs/1_46_0/libs/smart_ptr/smart_ptr.htm
You could use std::auto_ptr


Er, not, std::auto_ptr isn't meant to contain arrays. Nor is boost::shared_ptr.
It seems to have been overlooked, due to the specifics of the questions here, but why not just use an STL container of strings?

1
2
3
vector< string > arr( 10 );
arr[0] = "asdf";
// etc. 


A vector can be dynamically resized and cleans up after itself. Explicitly reserving the number of elements (10) yields performance very comparable to an array allocated with new.
Just bumping in to clear up a misconception here:

You mean that p_array objects I must delete in my code. But parr objects will be deleted by OS.


Actually, it's that your compiler will generate code to destroy parr objects once they leave their scope, the OS doesn't do much here. If you don't explicitly call delete on p_array, the memory you have allocated will be deallocated anyways by your OS once the program terminates. Which means that in this simplistic case, you wouldn't really need to delete the array manually. However, manually allocated memory will belong to your program as long as your program is running or until you delete them yourself- this can quite quickly lead to memory problems (not so much with these small practice programs, but in a more realistic situation the memory you can't use anymore due to you not deallocating it properly can quickly reach some troublesome amounts).

Oh and as to the auto_ptr thing: Uh... STL anyone? auto_ptrs don't work with arrays, but STL containers free their occupied memory upon destruction...
Last edited on
If you don't explicitly call delete on p_array, the memory you have allocated will be deallocated anyways by your OS once the program terminates.
Not strictly true. The resources used by the program will be released (mostly). p_array isn't really released, but the OS memory block from which it was suballocated will be released.

auto_ptrs don't work with arrays
Agreed, I should never have mentioned it.
moorecm, thank you.
Yes, vector< string > would be more appropriate and safe.

BTW, I am sorry, I clicked twice on Report button of your posts (yesterday and now).
The interface is not convenient here. It is my personal opinion.
Last edited on
kbw and firedraco, thank you.

If I know (I have only some knowledge of boost library, mostly theoretical), boost::scoped_ptr is just like classic pointer, only safe pointer. I mean it should be used only like a stand-alone pointer, with very limited usage.
Also std::auto_ptr is like obsolete version of boost::scoped_ptr pointers.

If it is wrong, please, correct me.

Not strictly true. The resources used by the program will be released (mostly). p_array isn't really released, but the OS memory block from which it was suballocated will be released.

You mean my example gives some memory leak anyway, don't you? ( You used the word mostly. It means something was not released)
Last edited on
No, you're fine. The mostly applies to shared memory.
Topic archived. No new replies allowed.