0

I've illustrated the problem with comments in the below code:

class MyClass //Some string-like class that encapsulates a dynamic char array.
{
public:
MyClass(unsigned int size)
{
data = new char[size];
}

char* GetCharArray() //In places where passing the raw array is needed, I call this method, but I want to create a separate char array and not touch the original one.
{
 char* temporary = new char[size + someNumber];
 for(int i = 0; i < size; i++)
 {
   temporary[i] = data[i];
 }
 DoSomeOperationForRemainingCharacters(temporary);
 return(temporary);
}
private:
char* data;
unsigned int size;
};

void SomeFunc(char* c);

int main()
{
 MyClass string(50):
 SomeFunc(string.GetCharArray()); //A new char array is allocated here, but it is
    // never deleted. If I return a templated pointer wrapper that wraps the array
    // and deletes it in the destructor, the wrapper dies at the end of
    // GetCharArray(), so by the time it's passed to SomeFunc(), the char array is
    // already deleted. What else can I do?
}

Maybe I need to make some small mini-garbage collection system?

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
ulak blade
  • 2,515
  • 5
  • 37
  • 81
  • 2
    Is there a good reason for reinventing `std::vector` (or `std::string`) rather than just using it? If so, you should use [RAII](http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization) to reinvent it properly - that's the conventional "mini-garbage collection system" in C++. – Mike Seymour Feb 26 '14 at 12:31

2 Answers2

3

Why do you return char*? you can return std::string instead which will manage its own memory.

Or when using arrays of other types std::vector will manage storage for you

You where hiding a comment in your code that might explain the source of your confusion - //A new char array is allocated here, but it is never deleted. If I return a templated pointer wrapper that wraps the array and deletes it in the destructor, the wrapper dies at the end of GetCharArray(), so by the time it's passed to SomeFunc(), the char array is already deleted. What else can I do?

Your statement is incorrect. The temporary will die after the entire expression is evaluated Lets assume these functions exist:

void SomeFunc(const char* input); //old style C function that expects a raw char pointer

//creates a temporary string and returns it
std:string GetString() {
   std::string temp = "whatever";
      ... lots of manipulation ...
   return temp;
}

And you evaluate this expression:

SomeFunc(GetString().c_str());

The C++ Standard guarantee that the temporary string returned by GetString() will only be deallocated when the entire expression is evaluated. with c++11 move-ctor the temporary char array inside std::string will not be copied unnecessarily

odedsh
  • 2,594
  • 17
  • 17
  • When I try to do something like GetString().c_str() with my custom class, the temporary string dies before the valid char array is read by SomeFunc. How is it made to not be destroyed so early on in std? If I do this: std::string temp = GetString(); SomeFunc(temp.c_str()); then it works. Maybe I need to do something with the move constructor> – ulak blade Feb 26 '14 at 12:35
  • You must be doing something else wrong. I bet you did not provide proper copy-ctor, operator=, move-ctor. in your temporary class. Read about the rule of 3 http://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming) Also http://stackoverflow.com/questions/4782757/rule-of-three-becomes-rule-of-five-with-c11 – odedsh Feb 26 '14 at 12:38
  • but why bother with creating a class when you can use `std::string` which was created by experts? – odedsh Feb 26 '14 at 12:38
  • I'm making an immutable one, it's nothing big, only this issue with returning the raw array remains. Btw a move constructor for a string has to replace the raw arrays in the left and right string, right? So the one from the left can be destroyed when the right one dies and for the left one to keep the array from the right one. – ulak blade Feb 26 '14 at 12:40
  • Regarding immutable.. You can still return an std::string instead of a char*. It is still a new temporary object that can't affect the state of your object – odedsh Feb 26 '14 at 12:44
  • Regarding move-ctor. `MyObject(MyObject&& in)` You steal the resources of `in` for your own. You should clean the state of in so you do not share resources and when its destructor is called a second later it won't release anything you now own – odedsh Feb 26 '14 at 12:46
  • One final comment. const std::string as an immutable string. No? I mean the immutable version of an object is available using the const keyword. – odedsh Feb 26 '14 at 17:17
0

Use std::string to return char-based strings.

It handles memory allocation and deallocation for you.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331