我有以下问题。应该遵循哪一项更好?为什么?
string strMyString = "SampleString";
或
string strMyString("SampleString");
我回答了这里
我在这里回答的一件事是:都没有使用任何赋值运算符。
对字符串特定事物的简短解释。
std::string
有一个构造函数,它接受一个接受 char const*
: 的参数
// simplified to a normal class declaration. std::string actually
// is a template instantiation.
class string {
public:
string(char const* str) {
// copy over...
}
};
现在你看到有一个构造函数,它带有一个指向字符的指针。这样它就可以接受字符串文字。我认为以下情况是显而易见的:
string s("hello");
它将直接调用构造函数并由此初始化
s
。这称为“直接初始化”。
初始化变量的另一种方法称为“复制初始化”。标准规定,对于复制初始化的情况,如果初始化器不具有正在初始化的对象的类型,则初始化器将转换为正确的类型。
// uses copy initialization
string s = "hello";
首先我们先来说一下类型
s
的类型为 std::string
"hello"
char const*
。 编译器寻找两种方法来进行转换。std::string 中有
初始化器的类型是否具有返回
std::string
std::string
,然后使用
s
来初始化对象
std::string
。它看到 std::string
has一个接受初始化器的转换构造函数。所以它使用它。最后,它实际上与 相同
std::string s(std::string("hello"));
请注意,示例中使用的表单触发了所有这些
std::string s = "hello";
定义了隐式转换
。如果您想知道您的东西的初始化规则,您可以将采用
char const*
的构造函数标记为类型的explicit
,并且它将不再允许使用相应的构造函数作为 conversion constructor :
class string {
public:
explicit string(char const* str) {
// copy over...
}
};
这样,使用 copy initialization
和 char const*
来初始化它实际上现在是被禁止的(以及在其他各个地方)!
现在,如果编译器不支持在各个地方省略临时变量。编译器可以假设在这种情况下有一个复制构造函数
复制,并且可以消除临时字符串的额外副本,而是直接将临时 std::string 构造到初始化对象中。但是,复制构造函数必须特别可访问。所以,如果这样做的话,复制初始化是无效的
class string {
public:
explicit string(char const* str) {
// copy over...
}
private: // ugg can't call it. it's private!
string(string const&);
};
现在实际上只有直接初始化的情况才有效。
编译两者,查看汇编器。第一个是少了一条指令......
; 9 : std::string f("Hello");
push OFFSET ??_C@_05COLMCDPH@Hello?$AA@
lea ecx, DWORD PTR _f$[esp+80]
call DWORD PTR __imp_??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z
; 10 : std::string g = "Hello";
push OFFSET ??_C@_05COLMCDPH@Hello?$AA@
lea ecx, DWORD PTR _g$[esp+80]
mov DWORD PTR __$EHRec$[esp+88], 0
call DWORD PTR __imp_??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z
; 9 : std::string g1 = "Hello";
push OFFSET ??_C@_05COLMCDPH@Hello?$AA@
lea ecx, DWORD PTR _g1$[esp+136]
call DWORD PTR __imp_??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z
; 10 : std::string f1("Hello");
push OFFSET ??_C@_05COLMCDPH@Hello?$AA@
lea ecx, DWORD PTR _f1$[esp+136]
mov DWORD PTR __$EHRec$[esp+144], 0
call DWORD PTR __imp_??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z
...你瞧,第第二个
少了一条指令。
我们还看到这个编译器(Microsoft VC++ 2005,发布设置)为两个版本生成了相同的汇编程序。所以在这个编译器中没有什么区别,你可以证明这一点。
唯一真正的区别是,第一个在技术上需要使用复制构造函数,但允许编译器省略它,以便两种情况下的效率相同。
但是,第一个要求复制构造函数可访问(即不是私有的),即使它实际上并未使用。
其他答案都是正确的,但也请记住,
这可能并不重要。字符串初始化效率将非常罕见,非常罕见,非常罕见,甚至会影响程序的速度的一小部分。第二个。
,因为它有助于展示 C++ 构造函数和赋值的操作,但在实践中,如果你花时间尝试优化它(并且在 SO 上发布就足以证明你是这样的......)你'真的很倾斜风车。 最好避免分心,把精力花在其他地方。