初始化..哪一个更有效?

vj0*_*j01 10 c++ constructor initialization

我有以下问题.应该遵循哪一个更好,为什么?

string strMyString = "SampleString";
Run Code Online (Sandbox Code Playgroud)

要么

string strMyString("SampleString");
Run Code Online (Sandbox Code Playgroud)

提前致谢.

Joh*_*itb 21

在这里回答

我在这里回答的一件事:两者都没有使用任何赋值运算符.

尽管字符串具体的简短解释.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...
    }
};
Run Code Online (Sandbox Code Playgroud)

现在你看到有一个构造函数接受一个指向字符的指针.这样它就可以接受一个字符串文字.我认为以下情况很明显:

string s("hello");
Run Code Online (Sandbox Code Playgroud)

它将直接调用构造函数并s从而进行初始化.这称为直接初始化.

初始化变量的另一种方法称为复制初始化.标准说,对于复制初始化的情况,初始化程序没有初始化对象的类型,初始化程序将转换为正确的类型.

// uses copy initialization
string s = "hello";
Run Code Online (Sandbox Code Playgroud)

首先,让我们说明类型

  • s 有类型std :: string
  • "hello"是一个数组,在这种情况下再次像指针一样处理.我们将其视为char const*.

编译器寻找两种方法来进行转换.

  • std :: string中是否有转换构造函数
  • 初始化程序是否具有返回运算符函数的类型std::string

它会创建一个临时std::string用的那个,然后用来初始化对象的方式中的一种s使用std::string拷贝构造函数.它看到std::string 一个接受初始化器的转换构造函数.所以它使用它.最后,它实际上是一样的

std::string s(std::string("hello"));
Run Code Online (Sandbox Code Playgroud)

请注意,您的示例中使用的表单触发了所有这些

std::string s = "hello";
Run Code Online (Sandbox Code Playgroud)

定义隐式转换.您可以标记构造函数取char const*明确为你的类型,如果你想知道关于你的东西的初始化规则,它不会允许使用相应的构造函数作为转换构造了:

class string {
public:
    explicit string(char const* str) {
        // copy over...
    }
};
Run Code Online (Sandbox Code Playgroud)

有了它,现在禁止使用a copy initialization和a 初始化它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&);
};
Run Code Online (Sandbox Code Playgroud)

实际上,只有直接初始化情况才有效.


Tho*_*day 7

编译两者,看看汇编程序.首先是少一条指令......

; 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
Run Code Online (Sandbox Code Playgroud)

...但这是一个神器,因为它是编译器看到的第一个神器.通过交换订单更改代码:

; 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
Run Code Online (Sandbox Code Playgroud)

......而且,第二个是少一个指令.

我们还看到这个编译器(Microsoft VC++ 2005,Release设置)为两个版本生成了相同的汇编程序.所以它在这个编译器中没有任何区别,你可以证明它.