繁体   English   中英

以下声明之间的区别

[英]Difference between following declarations

最近,我对使用带有字符串数据类型的new关键字感到困惑。 能请您澄清一下吗

以下字符串初始化有什么区别:

1)

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

2)

string name = "abc";

建议使用new关键字,因为string中的值是如何作为std::string内部缓冲区存储在堆中的。 如果有人对它进行存储位置解释会很好。

返回字符串和字符串*有什么区别?

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

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

string是在当前范围中创建的实际字符串,并且在退出范围时将自动清除。

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

string*是指向未绑定到当前范围的字符串的指针。 指针从无效处开始(通常由用户分配nullptr ,这意味着它没有指向任何东西),并且您需要为其分配内存位置; 否则,访问它将会是一个错误。 当您使用new并为指针分配一个值时,您将拥有一个位于堆上且不在当前作用域中的字符串,并且需要手动delete它,否则会导致内存泄漏 您可以将指针包装在智能指针中,以使其自动删除。

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.

避免使用new分配对象的主要原因是,它比使用位于堆栈上的项目要慢,而使用 new主要原因是,将指针传递给对象而不是复制对象可能更快。

但是,尽管复制字符串的速度可能很慢,但是您也可以移动字符串,这样可以使其速度更快。

移动字符串只需将字符串A的内部缓冲区重新放置到字符串B中

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

您还可以显式移动字符串。

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

通常,std :: strings本身不是用new创建的,而是它们所在的结构或类。

一个使用指针的示例,我可能有一个特殊的类,可以传递给不同的函数:

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

MyClass::function1给我一个指向字符串的const指针,这意味着没有数据被复制,并且我只能读取字符串的值。

MyClass::function2基本上与MyClass::function2做相同的事情,但它使用引用代替,引用就像指针一样,但是它们必须始终包含有效的目标。 引用通常在C ++中通过指针使用。

MyClass::function3返回该字符串的一个副本,外部函数可以修改该副本,并且不会影响该类内部的字符串。

有几种原因比第一种更喜欢第二种方法:

  • 最重要的原因: string是一个string ,句点。 string*可以指向string ,或者可以为NULL / nullptr ,或者可以指向内存中的随机位置。 因此,应尽可能使用普通的旧string over string*因为使用它们不太容易出错。

  • 声明一个string对象将其放在堆栈上,这意味着它将在离开范围时自动清除。 使用new意味着您现在必须手动清理分配的内存。

  • new是一个相对较慢的操作。 使用堆栈变量要快得多。

虽然string存储将其数据存储在堆上,但在堆上分配string本身仍然会增加另一种间接性。

如果我们使用new运算符,则将在堆内存中创建对象,而引用指针将在堆栈中。 在您的示例中

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

name是存储在堆栈中的指针变量,其中包含字符串对象的地址。 实际对象存储在堆中。 因此它不会在方法执行后销毁。 调用方法将获取对象的地址,我们可以使用该地址进行引用。 我们需要使用'delete'关键字来释放字符串对象的内存。

例如:

delete name;

如果我们定义的字符串没有新的运算符,它将在堆栈本身中创建,并且在方法执行结束时将自动销毁它。 考虑这个例子,

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

在这里,将在方法名称的堆栈框架中创建一个对象,方法执行结束后,该对象将被销毁。

使用上述功能的语句将像

 string a = name();

在这里,将调用字符串类的operator =()方法,并在调用函数的堆栈框架中创建一个新对象。

希望这会有所帮助

暂无
暂无

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

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