C ++字符串声明

时间:2011-11-09 17:35:00

标签: c++ string

我从一开始就学习C ++而且我没有得到整个字符串主题。

以下三个代码之间有什么区别?

  1. std::string s = std::string("foo");
  2. std::string s = new std::string("foo");
  3. std::string s = "foo";

5 个答案:

答案 0 :(得分:42)

std::string s = std::string("foo");

这将创建一个包含“foo”的临时std::string对象,然后将其分配给s。 (请注意,编译器可能会忽略临时。在这种情况下,临时elison是C ++标准明确允许的。)

std::string s = new std::string("foo");

这是一个编译器错误。表达式new std::string("foo") 在免费商店上创建std::string,并返回指向std::string的指针。然后,它尝试将类型为std::string*的返回指针分配给s类型的std::stringstd::string类的设计可防止这种情况发生,因此编译失败。

C ++不是Java。这不是通常创建对象的方式,因为如果忘记delete返回的std::string对象,则会泄漏内存。使用std::string的一个主要好处是它会自动为您管理基础字符串缓冲区,因此new使它失败了。

std::string s = "foo";

这与#1基本相同。它在技术上初始化一个包含“foo”的新临时字符串,然后将其分配给s。同样,编译器通常会忽略临时(实际上几乎所有非愚蠢的编译器实际上都消除了临时),因此在实践中它只是构建了一个名为s的新对象。

具体来说,它在std::string中调用一个接受const char*参数的转换构造函数。在上面的代码中,转换构造函数必须是非explicit,否则它是编译器错误。转换构造函数实际上是explicit的非std::string,所以上面的编译。

这是std::string通常初始化的方式。当s超出范围时,s对象将与底层字符串缓冲区一起被销毁。请注意,以下内容具有相同的效果(并且是另一种典型的std::string初始化方式),因为它还会生成一个名为s的对象,其中包含“foo”。

std::string s("foo");

但是,there's a subtle difference between std::string s = "foo"; and std::string s("foo");,其中之一就是转换构造函数在上述情况下可以是explicit或非explicit

答案 1 :(得分:3)

std::string s = std::string("foo");

这称为复制初始化。它在功能上与直接初始化相同

std::string s( "foo" );

但前者确实要求复制构造函数可用,编译器可能会创建一个临时对象,但大部分都会忽略临时对象并直接构造s以包含"foo"


std::string s = new std::string("foo");

这将无法编译,因为new返回一个指针。要使其有效,您需要s的类型为std::string *。然后该行动态分配std::string对象并将指针存储在s中。一旦你完成使用它,你需要delete


std::string s = "foo";

这与第一次几乎相同。它是复制初始化,但它有一个附加的约束。它要求std::string类包含一个非explicit构造函数,该构造函数需要const char *。这允许编译器隐式构造临时std::string对象。之后,语义与案例1完全相同。

答案 2 :(得分:2)

  1. 创建临时字符串对象并将值复制到s
  2. 不编译,new std::string("foo")返回指向一些新分配的内存的指针。 为此,您应该将s声明为指向字符串std::string* s的指针。
  3. 从C字符串构造一个字符串。
  4. 你应该在大多数情况下使用第三个选项 - 如果不是全部的话。

答案 3 :(得分:2)

1将创建一个临时变量(右侧),然后调用赋值运算符将值赋给s

2将在堆上创建std::string的实例并返回指向它的指针,并且在分配中将失败,因为您无法将指针指定给非指针类型

3将构建一个std :: string并从const char*

初始化它

答案 4 :(得分:1)

在数字1上,您将使用构造函数创建临时字符串,然后将其分配给s。 2号甚至没有编译。 在数字3上,您将创建一个新字符串,然后为其指定一个值。