虽然所有 3 种方法的最终结果是相同的(字符串将分配给变量),但存在一些比语法更深层次的基本差异。我将介绍您的 3 个字符串涵盖的所有 3 个场景:
第一种情况:s1是直接初始化的例子。直接初始化涵盖了许多不同的场景,您的定义如下:
使用带括号的非空表达式列表进行初始化。
这里s1没有class数据类型而是std::string数据类型,所以会进行标准转换,将括号中的数据类型转换为s1的cv-unqualified版本,即const *char . cv-unqualified 表示变量没有附加限定符,例如 (const) 或 (volatile)。请注意,在直接初始化的情况下,它比复制初始化要宽松得多,复制初始化是 s2 的主题。这是因为复制初始化只会引用用户定义的non_explicit(即隐式)的构造函数和转换函数。另一方面,直接初始化考虑隐式和显式构造函数以及用户定义的转换函数。
接下来,第二个字符串 s2 是复制初始化的一个示例。简而言之,它将值从左侧复制到右侧。这是一个例子:
当一个非引用类型 T 的命名变量(自动、静态或线程局部)被声明时,初始化器由等号后跟一个表达式组成。
此方法涵盖的过程是相同的。由于 s2 没有类数据类型而是std::string 数据类型,所以它将使用标准转换将右侧字符串的值转换为左侧const *char 类型的值。但是,如果显式声明函数,则不能像复制初始化器那样进行标准转换,代码编译会失败。
查看一些与 2 种初始化类型进行比较的代码示例。这应该可以消除上面的任何混淆:
struct Exp { explicit Exp(const char*) {} }; // This function has an explicit constructor; therefore, we cannot use a copy initialization here
Exp e1("abc"); // Direct initialization is valid here
Exp e2 = "abc"; // Error, copy-initialization does not consider explicit constructor
struct Imp { Imp(const char*) {} }; // Here we have an implicit constructor; therefore, a copy initializer can be used
Imp i1("abc"); // Direct initialization always works
Imp i2 = "abc"; // Copy initialization works here due to implicit copy constructor
继续第三种情况,它甚至不是初始化的情况,而是赋值的情况。就像您在 cmets 中所说的那样,变量 s3 使用默认字符串初始化。当您使用等号时,该字符串将替换为“Hello”。这里发生的是,当在string s3; 中声明s3 时,会调用std::string 的默认构造函数,并设置默认字符串值。当您使用 = 符号时,该默认字符串在下一行被替换为 hello。
如果我们在跑步时查看哪个在速度方面更有效,差异是微不足道的。但是,如果我们只这样做,s1 的运行时间会最快:
int main(void)
{
string a("Hello");
}
编译和运行需要以下时间和内存:
编译时间:0.32 秒,绝对运行时间:0.14 秒,cpu 时间:0 秒,内存峰值:3 Mb,绝对服务时间:0.46 秒
如果我们看一下按以下方式编码的字符串 s2:
int main(void)
{
string a = "Hello";
}
那么程序运行的总时间为:
编译时间:0.32 秒,绝对运行时间:0.14 秒,cpu 时间:0 秒,内存峰值:3 Mb,绝对服务时间:0.47 秒
使用复制初始化程序的运行时比直接初始化程序多花费 0.01 秒。差异是存在的,但只是微不足道的。
s3 的第三种情况,如果编码如下:
int main(void)
{
string a;
a = "Hello";
}
总运行、编译时间和空间占用:
编译时间:0.32 秒,绝对运行时间:0.14 秒,cpu 时间:0 秒,内存峰值:3 Mb,绝对服务时间:0.47 秒
我想在这里指出一点:第二种和第三种方法之间的运行时差异很可能NOT为零;相反,它的时间差小于 0.01 秒,第三种方法需要更长的时间(s3)。那是因为它有两行代码可以操作;一个是变量的声明,另一个是字符串对变量的赋值。
希望这能回答你的问题。