evk1206
evk1206

Reputation: 463

Difference between following declarations

Recent times I am confused with the use of new keyword with the string data type. Can you please try to clarify it

What's the difference between the following string initialization:

1)

string* name = new string("abc") ;
....
delete name;

2)

string name = "abc";

Is it advisable to use new keyword , as the values within string is any how stored in heap as internal buffers of std::string. It will be good if anyone explains it with storage location.

What's the difference between returning the string vs string*

string* name()
{
    string* name = new string("abc") ;
    return name;
}

string name()
{
    string name = "abc";
    return name;
}

Upvotes: 0

Views: 103

Answers (3)

ApproachingDarknessFish
ApproachingDarknessFish

Reputation: 14323

There are several reasons to prefer the second approach over the first:

  • Most important reason: a string is a string, period. A string* may point to a string, or it may be NULL/nullptr, or it may point to a random location in memory. Therefore, you should use plain old string's over string*'s wherever possible as using them is less prone to errors.

  • Declaring a string object places it on the stack, meaning that it will automatically cleaned up when it leaves scope. Using new means that you now have to manually clean up your allocated memory.

  • new is a relatively slow operation. Using stack variables is much faster.

While string store's its data on the heap, allocating the string itself on the heap still adds another level of indirection.

Upvotes: 1

mukunda
mukunda

Reputation: 2995

string is an actual string being created in the current scope, and it will be cleaned up automatically when the scope exits.

void function() {
    { // a scope
        string test = "hi";
    }
    // test is destroyed here and cannot be used.
}

string* is a pointer to a string that isn't tied to the current scope. A pointer starts out as invalid (usually assigned nullptr by the user, which means it doesn't point to anything), and you need to assign a memory location to it; it would be an error to access it if it wasn't. When you use new and assign a value to the pointer, then you have a string that is located on the heap and not in the current scope, and you need to delete it manually, otherwise the memory is leaked. You can wrap a pointer in a smart pointer to have it delete itself automatically.

void function() {
    {
        string *test = new string("hi");
    }
    // test is *not* destroyed and memory was leaked
}

void function() {
    unique_ptr<string> test;
    {
        test = unique_ptr<string>( new string("hi") );
    }

} // test is deleted when the function exits and the unique_ptr goes out of scope.

The main reason to avoid allocating objects with new is that it is slower than using items located on the stack, and the main reason to use new is that it may be faster to pass around a pointer to an object rather than copying the object.

However, while copying a string may be slow, you can also move a string, which makes it fast.

Moving a string simply relocates the internal buffers of string A into string B

string function() {
    string test = "abcdefg";
    return test; // when test is returned, it is moved to the calling function.
}

You can also move a string explicitly.

string A = "hello";
string B( std::move(A) );
// A is invalid, and B contains "hello"

Usually std::strings are not created with new by themselves, but rather a struct or class they reside in may be.

An example using pointers, I may have a special class that I pass around to different functions:

class MyClass {
    string a; 
public:
    const string *function1() { return &a; }
    const string &function2() { return a; }
    string function3() { return a; }
}

MyClass::function1 gives me a const pointer to the string, meaning no data is copied, and I can only read the string's value.

MyClass::function2 basically does the same thing as function1, but it uses a reference instead, references are like pointers but they must always contain a valid target. References are usually used in C++ over pointers.

MyClass::function3 returns a copy of the string, which an outside function can modify and it won't affect the one inside the class.

Upvotes: 1

shintoZ
shintoZ

Reputation: 311

If we are using the new operator, the object will be created in heap memory and the reference pointer will be in stack. In your example,

string* name()
{
 string* name = new string("abc") ;
 return name;
}

name is a pointer variable which is stored in stack, that contains the address of string object. The actual object is stored in the heap. So it wont be destroyed after the method execution. The calling method will get the address of the object and we can refer it using that. We need to deallocate the string object memory using the 'delete' keyword.

Ex:

delete name;

If we are defining a string without new operator, it will be created in the stack itself and it will be automatically destroyed when the method execution gets over. Consider the example,

string name()
{
  string name = "abc";
  return name;
}

Here one object will be created in the stack frame of method name, after the method execution over, it will get destroyed.

The statement that uses the above function will be like

 string a = name();

Here the operator=() method for the string class will be invoked and a new object will be created in the calling function's stack frame.

Hope this will help

Upvotes: 0

Related Questions