首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >成员初始化列表真的更有效率吗?

成员初始化列表真的更有效率吗?
EN

Stack Overflow用户
提问于 2017-02-15 21:31:41
回答 3查看 1.8K关注 0票数 8

我同意这样的共识,即通常最好在成员初始化列表中初始化C++数据成员,而不是构造函数的主体,但我对这一解释持怀疑态度

构建构造函数的另一种(低效)方法是通过赋值,例如:Fred::Fred() { x_ = whatever; }. --在这种情况下,表达式任何导致创建一个单独的临时对象,并且这个临时对象被传递给x_对象的赋值运算符。然后在;上销毁该临时对象。那是低效的。

这是真的吗?我原以为编译器会删除默认构造的临时对象,该对象将立即被主体中的赋值所取代。我不知道为什么我会这样想,但在阅读了上面的声明之后,我想我已经悄悄地假设了多年了。

成员初始化列表实际上更有效率吗?如果是的话,是否因为这个原因呢?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-02-15 21:52:22

使用成员项列表,

代码语言:javascript
复制
#include <string>

struct Fred {
  Fred() : x_("hello") { }
  std::string x_;
};

int main() {
  Fred fred;
}

Clang3.9.1和gcc 6.3使用-O3 -fno-exceptions (编译器资源管理器)生成以下内容:

代码语言:javascript
复制
main:                                   # @main
        xor     eax, eax
        ret

如果我们在身体里做一项任务,那么:

代码语言:javascript
复制
#include <string>

struct Fred {
  Fred() { x_ = "hello"; }
  std::string x_;
};

int main() {
  Fred fred;
}

两者都生成了更多的代码,例如Clang 3.9.1输出如下:

代码语言:javascript
复制
main:                                   # @main
        push    rbx
        sub     rsp, 32
        lea     rbx, [rsp + 16]
        mov     qword ptr [rsp], rbx
        mov     qword ptr [rsp + 8], 0
        mov     byte ptr [rsp + 16], 0
        lea     rdi, [rsp]
        xor     esi, esi
        xor     edx, edx
        mov     ecx, .L.str
        mov     r8d, 5
        call    std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_replace(unsigned long, unsigned long, char const*, unsigned long)
        mov     rdi, qword ptr [rsp]
        cmp     rdi, rbx
        je      .LBB0_2
        call    operator delete(void*)
.LBB0_2:
        xor     eax, eax
        add     rsp, 32
        pop     rbx
        ret

.L.str:
        .asciz  "hello"

因此,似乎成员init列表确实更有效率,至少在某些情况下,即使在现代编译器中也是如此。

票数 9
EN

Stack Overflow用户

发布于 2017-02-15 21:37:33

Alexandrescu & Sutter (第9项)的话说,不要过早地悲观

避免过早优化并不意味着不必要地损害效率。所谓过早的悲观,我们指的是写这样的无端的潜在的低效,如: ·当引用传递合适时,定义逐值传递参数。(见Item25.) 在前缀版本同样好的情况下使用后缀++。(见项目28) 使用构造函数内部的赋值,而不是初始化程序列表。(见项目48)

每当您在构造函数中编写作业时,代码审阅者都会保持警惕:有什么特别的事情发生吗?他真的想要一些特殊的两阶段初始化(因为有一个默认的成员结构正在生成!)。不要让你代码的读者感到意外。

请注意,Alexandrescu & Sutter继续在第48项中讨论潜在的低效率,但不要声称在实际优化的代码中存在实际的低效率。这也不重要,它是关于表达意图和避免低效率的风险。

票数 10
EN

Stack Overflow用户

发布于 2017-02-15 21:43:09

成员初始化列表实际上更有效率吗?如果是的话,是否因为这个原因呢?

一般是的。通过成员初始化,您直接将值传递给构造函数,否则将创建一个默认构造的对象,然后调用赋值运算符。注意,这不是您提供的引号中提到的“临时”,而是字段本身。

你可以看到它是实时的这里

代码语言:javascript
复制
class Verbose {
public:
    Verbose() { std::cout << "Verbose::Verbose()" << std::endl; }
    Verbose( int ) { std::cout << "Verbose::Verbose(int)" << std::endl; }
    Verbose &operator=( int )  { std::cout << "Verbose::operator=(int)" << std::endl; }
};

class A {
public:
    A() : v( 0 ) {}
    A(int)  { v = 0; }
private:
    Verbose v;    
};


int main() {
    std::cout << "case 1 --------------------" << std::endl;
    A a1;
    std::cout << "case 2 --------------------" << std::endl;
    A a2( 0 );
    // your code goes here
    return 0;
}

产出:

代码语言:javascript
复制
case 1 --------------------
Verbose::Verbose(int)
case 2 --------------------
Verbose::Verbose()
Verbose::operator=(int)
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42260463

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档