以下声明之间的区别

时间:2014-11-27 05:55:43

标签: c++ string

最近,我对使用字符串数据类型的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;
}

3 个答案:

答案 0 :(得分:1)

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不是自己创建的,而是它们所在的结构或类可能是。

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

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

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

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

MyClass::function3返回字符串的副本,外部函数可以修改它,它不会影响类中的字符串。

答案 1 :(得分:1)

有几个理由比第一种方法更喜欢第二种方法:

  • 最重要的原因:stringstring,期间。 string*可以指向string,也可以指向NULL / nullptr,也可以指向内存中的随机位置。因此,您应该尽可能使用普通的string而不是string*,因为使用它们不容易出错。

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

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

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

答案 2 :(得分:0)

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

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

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

例如:

delete name;

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

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

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

使用上述功能的语句将类似于

 string a = name();

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

希望这会有所帮助