简体   繁体   English

以下声明之间的区别

[英]Difference between following declarations

Recent times I am confused with the use of new keyword with the string data type. 最近,我对使用带有字符串数据类型的new关键字感到困惑。 Can you please try to clarify it 能请您澄清一下吗

What's the difference between the following string initialization: 以下字符串初始化有什么区别:

1) 1)

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

2) 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 . 建议使用new关键字,因为string中的值是如何作为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;
}

string is an actual string being created in the current scope, and it will be cleaned up automatically when the scope exits. string是在当前范围中创建的实际字符串,并且在退出范围时将自动清除。

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. string*是指向未绑定到当前范围的字符串的指针。 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; 指针从无效处开始(通常由用户分配nullptr ,这意味着它没有指向任何东西),并且您需要为其分配内存位置; 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 . 当您使用new并为指针分配一个值时,您将拥有一个位于堆上且不在当前作用域中的字符串,并且需要手动delete它,否则会导致内存泄漏 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. 避免使用new分配对象的主要原因是,它比使用位于堆栈上的项目要慢,而使用 new主要原因是,将指针传递给对象而不是复制对象可能更快。

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 移动字符串只需将字符串A的内部缓冲区重新放置到字符串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. 通常,std :: strings本身不是用new创建的,而是它们所在的结构或类。

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::function1给我一个指向字符串的const指针,这意味着没有数据被复制,并且我只能读取字符串的值。

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. MyClass::function2基本上与MyClass::function2做相同的事情,但它使用引用代替,引用就像指针一样,但是它们必须始终包含有效的目标。 References are usually used in C++ over pointers. 引用通常在C ++中通过指针使用。

MyClass::function3 returns a copy of the string, which an outside function can modify and it won't affect the one inside the class. MyClass::function3返回该字符串的一个副本,外部函数可以修改该副本,并且不会影响该类内部的字符串。

There are several reasons to prefer the second approach over the first: 有几种原因比第一种更喜欢第二种方法:

  • Most important reason: a string is a string , period. 最重要的原因: string是一个string ,句点。 A string* may point to a string , or it may be NULL / nullptr , or it may point to a random location in memory. string*可以指向string ,或者可以为NULL / nullptr ,或者可以指向内存中的随机位置。 Therefore, you should use plain old string 's over string* 's wherever possible as using them is less prone to errors. 因此,应尽可能使用普通的旧string over string*因为使用它们不太容易出错。

  • Declaring a string object places it on the stack, meaning that it will automatically cleaned up when it leaves scope. 声明一个string对象将其放在堆栈上,这意味着它将在离开范围时自动清除。 Using new means that you now have to manually clean up your allocated memory. 使用new意味着您现在必须手动清理分配的内存。

  • new is a relatively slow operation. new是一个相对较慢的操作。 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. 虽然string存储将其数据存储在堆上,但在堆上分配string本身仍然会增加另一种间接性。

If we are using the new operator, the object will be created in heap memory and the reference pointer will be in stack. 如果我们使用new运算符,则将在堆内存中创建对象,而引用指针将在堆栈中。 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. name是存储在堆栈中的指针变量,其中包含字符串对象的地址。 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. 我们需要使用'delete'关键字来释放字符串对象的内存。

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. 在这里,将调用字符串类的operator =()方法,并在调用函数的堆栈框架中创建一个新对象。

Hope this will help 希望这会有所帮助

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM