I want to return a name, and while the main should be able to alter it (in main's scope), it should not change in the class.
If I do it like this:
char* get_name(){
char* name = new char[sizeof(_name)+1];
strcpy(_name,name);
return name;
}
do I have to delete[] at some point? And when?
Edit: I don't believe it's the same problem as pointer to local variable since the problem here is how to delete it after i use it.
Well, that's the problem with manual memory management. Indeed, if you want to return a copy, then it would be the caller's responsibility to free the memory, which is extremely error prone. That's why C++ has std::string class which handles the memory;
std::string get_name() const //note the const on member function
{
return _name; //this will work even if _name is char*, btw
}
As others have said, using std::string is probably a better option. If you want to use a char* instead, I would suggest simply returning a const char*:
const char* get_name() {
return _name;
}
You will be returning a const reference, meaning that the calling code should not change it. The way you are doing it, you will indeed have to delete after every call to get_name(), which is not ideal.
You will indeed have to delete[] the returned pointer at some point: since every new[] must be balanced with a delete[]. That can be difficult to manage.
But why not maintain a std::string member in your class, and write
const std::string& getName() const
{
return name; // name is the class member.
}
instead? Returning a const reference obviates a deep copy and also means the caller cannot modify the member.
First of all I think you mean
strcpy( name, _name );
^^^^^^^^^^^
instead of
strcpy( _name, name );
^^^^^^^^^^^
The object of the class that returns the pointer to the dynamically allocated memory will not have access to this memory after returning the pointer.
So it is the client of the function who shall free the allocated memory.
As other already pointed it is better to use standard class std::string in such cases.
Related
class Student {
private:
int age;
public:
char *name;
Student(int age,char*name) {
this->age=age;
this->name=new char[strlen(name)+1];
strcpy(this->name,name);
}
Student(Student const &s1) {
this->age=s1.age;
this->name=new char[strlen(s1.name)+1];
strcpy(this->name,s1.name);
s1.name[0]='x';
}
void display() {
cout<<age<<" "<<name<<endl;
}
};
int main() {
char name[]="abcd";
Student s1(10,name);
s1.display();
Student s2(s1);
s2.name[0]='x';
s1.display();
s2.display();
}
I have passed s1 as a constant reference but I am able to change s1.name[0] and the program compiles successfully. Why I am able to change s1.name[0]?enter image description here
You did not modify s1. You modified some unrelated memory block (allocated by new) , to which s1 holds a pointer. In C++ there is no special relationship between a raw pointer and any memory block it might happen to be pointing to.
If you use std::string instead of raw pointers and manual memory management then this problem will not arise.
As others have already said this is because s1 is const, so you cannot modify the pointer s1.name. However, the memory s1.name is pointing at is not const.
If you really cannot use std::string, you might want to have a look at std::experimental::propagate_const. This is a wrapper for any pointer type, in your case a raw pointer, that will, as the name suggests, propagate its constness to the memory it points at.
But as I can hardly imagine any circumstances where you are not able/allowed to use an std class (string), but an std::experimental class would be ok, this is likely not an option for you. However, you might get inspired by the idea and write your own string class.
Note in case you are not aware: you are missing a corresponding delete for your new. std::string would do that for you. So, if you write your own string class, make sure that one also does that.
I have a function f returning a char*. The function documentation says:
The user must delete returned string
I want to construct a std::string from it. The trivial things to do is:
char* cstring = f();
std::string s(cstring);
delete cstring;
Is it possibile to do it better using C++ features? I would like to write something like
std::string(cstring)
avoiding the leak.
std::string will make a copy of the null terminated string argument and manage that copy. There's no way to have it take ownership of a string you pass to it. So what you're doing is correct, the only improvement I'd suggest is a check for nullptr, assuming that is a valid return value for f(). This is necessary because the std::string constructor taking a char const * requires that the argument point to a valid array, and not be nullptr.
char* cstring = f();
std::string s(cstring ? cstring : "");
delete[] cstring; // You most likely want delete[] and not delete
Now, if you don't need all of std::string's interface, or if avoiding the copy is important, then you can use a unique_ptr to manage the string instead.
std::unique_ptr<char[]> s{f()}; // will call delete[] automatically
You can get access to the managed char * via s.get() and the string will be deleted when s goes out of scope.
Even if you go with the first option, I'd suggest storing the return value of f() in a unique_ptr before passing it to the std::string constructor. That way if the construction throws, the returned string will still be deleted.
There is no standard way for a std::string to take ownership of a buffer you pass.
Nor to take responsibility of cleaning up such a buffer.
In theory, an implementation, knowing all the internal details, could add a way for a std::string to take over buffers allocated with their allocator, but I don't know of any implementation which does.
Nor is there any guarantee doing so would actually be advantageous, depending on implementation-details.
This code can never be correct:
std::string s(cstring);
delete cstring;
The std::string constructor that takes a character pointer, requires a NUL-terminated string. So it is multiple characters.
delete cstring is scalar delete.
Either you are trying to create a string from a character scalar (in which case, why the indirection?)
std::string s(cstring[0]);
delete cstring;
or you have multiple characters, and should delete accordingly
std::string s(cstring);
delete [] cstring;
Check the other answers for the recommended way to make sure delete[] gets used, e.g.
std::string(std::unique_ptr<char[]>(f()).get())
std::string steal_char_buffer( std::unique_ptr<char[]> buff ) {
std::string s = buff?buff.get():""; // handle null pointers
return s;
}
std::string steal_char_buffer( const char* str ) {
std::unique_ptr<char[]> buff(str); // manage lifetime
return steal_char_buffer(std::move(buff));
}
now you can type
std::string s = steal_char_buffer(f());
and you get a std::string out of f().
You may want to make the argument of steal_char_buffer be a const char*&&. It is mostly pointless, but it might lead to some useful errors.
If you can change the interface of f, make it return a std::string directly or a std::unique_ptr<char[]>.
Another good idea is to wrap f in another function that returns a std::unique_ptr<char[]> or std::string:
std::unique_ptr<char[]> good_f() {
return std::unique_ptr<char[]>(f());
}
and/or
std::string good_f2() {
auto s = good_f();
return steal_char_buffer( std::move(s) );
}
I have a function f returning a char*. The function documentation says:
The user must delete returned string
I want to construct a std::string from it. The trivial things to do is:
char* cstring = f();
std::string s(cstring);
delete cstring;
Is it possibile to do it better using C++ features? I would like to write something like
std::string(cstring)
avoiding the leak.
std::string will make a copy of the null terminated string argument and manage that copy. There's no way to have it take ownership of a string you pass to it. So what you're doing is correct, the only improvement I'd suggest is a check for nullptr, assuming that is a valid return value for f(). This is necessary because the std::string constructor taking a char const * requires that the argument point to a valid array, and not be nullptr.
char* cstring = f();
std::string s(cstring ? cstring : "");
delete[] cstring; // You most likely want delete[] and not delete
Now, if you don't need all of std::string's interface, or if avoiding the copy is important, then you can use a unique_ptr to manage the string instead.
std::unique_ptr<char[]> s{f()}; // will call delete[] automatically
You can get access to the managed char * via s.get() and the string will be deleted when s goes out of scope.
Even if you go with the first option, I'd suggest storing the return value of f() in a unique_ptr before passing it to the std::string constructor. That way if the construction throws, the returned string will still be deleted.
There is no standard way for a std::string to take ownership of a buffer you pass.
Nor to take responsibility of cleaning up such a buffer.
In theory, an implementation, knowing all the internal details, could add a way for a std::string to take over buffers allocated with their allocator, but I don't know of any implementation which does.
Nor is there any guarantee doing so would actually be advantageous, depending on implementation-details.
This code can never be correct:
std::string s(cstring);
delete cstring;
The std::string constructor that takes a character pointer, requires a NUL-terminated string. So it is multiple characters.
delete cstring is scalar delete.
Either you are trying to create a string from a character scalar (in which case, why the indirection?)
std::string s(cstring[0]);
delete cstring;
or you have multiple characters, and should delete accordingly
std::string s(cstring);
delete [] cstring;
Check the other answers for the recommended way to make sure delete[] gets used, e.g.
std::string(std::unique_ptr<char[]>(f()).get())
std::string steal_char_buffer( std::unique_ptr<char[]> buff ) {
std::string s = buff?buff.get():""; // handle null pointers
return s;
}
std::string steal_char_buffer( const char* str ) {
std::unique_ptr<char[]> buff(str); // manage lifetime
return steal_char_buffer(std::move(buff));
}
now you can type
std::string s = steal_char_buffer(f());
and you get a std::string out of f().
You may want to make the argument of steal_char_buffer be a const char*&&. It is mostly pointless, but it might lead to some useful errors.
If you can change the interface of f, make it return a std::string directly or a std::unique_ptr<char[]>.
Another good idea is to wrap f in another function that returns a std::unique_ptr<char[]> or std::string:
std::unique_ptr<char[]> good_f() {
return std::unique_ptr<char[]>(f());
}
and/or
std::string good_f2() {
auto s = good_f();
return steal_char_buffer( std::move(s) );
}
i have a STL string member variable in my class,
class A {
public:
const char* getData1() const { return data.c_str());
const string& getData2() const { return _data; }
private:
string _data;
};
getData1() vs. getData2(), which one is better?
The one returning a string reference is the better of the two choices. If the string is changed internally, a previously returned string reference would still be valid, but the const char * probably would not be.
Better than either of those choices may be to just return by value.
std::string getData3() const { return data_; }
Also, I'd suggest not prefixing variables with an underscore, and get rid of that using namespace std; statement.
Generally I prefer getData2(). The const char* returned by c_str() method can only be used as long as data's non-const methods are not called. After that, the content of const char* is undefined. By returning const char*, you are masking this issue. If the user of the class needs to use a C-style string, he can call c_str() himself on the returned const string&.
Here we are also assuming that the user of getData2() reasonably assumes that the returned reference will only available to him as long as the object of class A is not destroyed yet.
Both are a little dangerous because your object may go out of scope, or its memory may be freed. But you'll still have a pointer or reference to one of its members.
If you really want to do this though, it just depends on if you want access to the string methods or not. Also c_str()'s const char* may be memory that will be freed on you.
If _data is not that big maybe just return a string, not a const string&.
Returning a const string& is better. If you need a const char*, you can just call getData2().c_str() which is practically identical to what getData1() does.
Remember std::strings are better than const char* strings because they store the length, instead of being null terminated. This means if you want to get the length of that string, strlen(getData1()) is an O(n) operation, but getData2().length() is an O(1) operation.
I have a function for which I cannot change the function parameters. I need to return a const reference to a std::string created in this function. I tried to use boost shared_ptr, but this doesn't work. Why? How do I make this work?
const std::string& getVal(const std::string &key) {
boost::shared_ptr<std::string> retVal(new std::string());
... //build retVal string with += operator based on key
return *retVal;
}
You can't return a reference to a local variable from a function with c++. Although in c++0x this is possible.
Allocate the string on the heap and manually cleanup later:
If you cannot change the function's interface, then you will need to create it on the heap and then manually delete it after.
//Remember to free the address that getVal returns
const std::string& getVal(const std::string &key) {
std::string *retVal = new std::string();
... //build retVal string with += operator based on key
return *retVal;
}
Same solution but not manually:
Since the above will eventually lead to a memory leak if you forget to free it manually. I would recommend to wrap this call into a class and use RAII. I.e. in the constructor, call getVal and set a member of this class to point to it. In the destructor of your class you would delete it.
Why the code you gave with shared_ptr does not work:
shared_ptr works via reference counting. Since you are destroying the only shared_ptr object (by scope), there are no references left and the memory will be freed. To get this to work you'd have to return a shared_ptr, but you said you cannot do this.
You would need to return a boost shared_ptr, not a std::string. As soon as the function exits that shared_ptr on the stack will go out of scope and because there's only one reference it will be deleted. You would also need to return a copy not a reference.
You should never return a reference to a stack variable because again, as soon as the function exists it will be deleted.
If you cannot change the return type then the only (icky) option would be to allocate the string on the heap, return a reference to the pointer, and make sure the calling code knows it's a pointer and later deletes it.
E.g.
const std::string& getVal(const std::string &key) {
return *(new std::string("Something"));
}
// get the val, remember we must delete this pointer!
std::string* pString = &getVal("SomeKey");
delete pString;
This is not a boost issue. You cannot return a reference to a local variable, as the variable will cease to exist once the function terminates. In a case like this, you should really return a value. However, one hack you can use is to make the local variable static, but this may well cause concurrency and other problems.
Since you can't change the function's signature, you can return a reference to a static variable:
const std::string& getVal(const std::string &key) {
static std::string retVal;
... //build retVal string with += operator based on key
return retVal;
}
There are serious problems with this approach though. It is inherently not-thread safe. Even if your app is not multi-threaded, it can cause problems depending on how long the caller holds on to the reference.
If your app is not multi-threaded and each call to getVal() immediately uses or copies the string, then you can probably get away with this. But I would strongly recommend just returning a std::string.
Since what you want is the const reference, you could return by value and make the caller receive it with const reference.
Herb Sutter GotW 88
Another point to consider is that the standard allows a compiler to optimize away copies if it is possible. The standard refers to this a copy elision, however most people know it as "Named Return Value Optimisation" see here.
The basic concept is that where possible the compiler will construct the local object directly on to the object that is the result of the function call:
class A {};
A foo () {
A a; // #1
return a;
}
void bar () {
A b = foo(); // #2
}
In the above example 'a' will be constructed in the same location as 'b' in bar, and so when the function returns no copy is needed at all. In conclusion it might be worth while testing your compiler to see if it performs this optimization. The standard reference for this is 12.8/15 if your interested.