2016-04-19 23 views
1

初期化子リストが通常のコンストラクタボディ(デフォルトのコンストラクトとコンストラクションの後に代入を行う)に比べて優れていることは承知しています。コンストラクタのコンパイラの最適化

私は、最新のコンパイラの最適化機能も認識しています。

非初期化子リストコンストラクタを前者のタイプに最適化するのにスマートなコンパイラはありますか?はいの場合は、基本型だけに限定されているのですか、またはユーザー定義型も同様に含まれていますか?そうでない場合は、どうしてですか?

+0

多くの場合、それは単なる有利なことではない。その*必須*。 'const'メンバ、参照メンバ、またはデフォルト以外の構成可能なメンバ以外のメンバがメンバ初期化リストに参加する必要があります。 – WhozCraig

+0

私はそれらも認識しています。しかし、問題は両方が有効である場合についてです。 – CinCout

+0

あなたは確かにそうかもしれませんが、あなたの最初の文章を見ている外部の読者は*そうでないかもしれません。そうでなければ私はそれを言及しなかったでしょう。 – WhozCraig

答えて

1

gcc5.3が-O2を使ってどのように処理するかを示します。あなたの疑惑は正しい - 簡単なケースでは、オプティマイザはプログラミングが厄介なものになります。

コンパイラがメンバ変数のコンストラクタまたは代入演算子(この場合、別の変換単位で定義されているため)を見ることができない場合に問題が発生します。

それが起こるとき、あなたは(少なくとも、GCCと、私はすべての他のものと疑われる)、より良いコードを取得コンストラクタは、適切に書かれている場合:

テストコード:

#include <string> 

struct bar 
{ 
    bar(std::string = {}, std::string = {}); 
    bar(bar&&); 
    bar& operator=(bar&&); 
}; 

struct foo 
{ 
    __attribute__((noinline)) 
    foo(int x, double y, std::string z, std::string o, std::string p) 
    { 
    a = x; 
    b = y; 
    c = z; 
    _bar = bar(o, p); 
    } 
    int a; 
    double b; 
    std::string c; 
    bar _bar; 
}; 

struct foo2 
{ 
    __attribute__((noinline)) 
    foo2(int x, double y, std::string z, std::string o, std::string p) 
    : a(x), b(y), c(std::move(z)), _bar(std::move(o), std::move(p)) 
    { 
    } 

    int a; 
    double b; 
    std::string c; 
    bar _bar; 
}; 


int main() 
{ 
    foo f(45, 12.2, "hello", "foo", "bar"); 
    foo2 f2(45, 12.2, "hello", "foo", "bar"); 

} 

例のアセンブラ出力:

.LC0: 
     .string "basic_string::_M_construct null not valid" 
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) [clone .isra.16]: 
     pushq %r13 
     pushq %r12 
     leaq 16(%rdi), %r12 
     pushq %rbp 
     pushq %rbx 
     subq $24, %rsp 
     testq %rsi, %rsi 
     movq %r12, (%rdi) 
     je  .L2 
     movq %rdi, %rbx 
     movq %rsi, %rdi 
     movq %rsi, %r13 
     call strlen 
     cmpq $15, %rax 
     movq %rax, %rbp 
     movq %rax, 8(%rsp) 
     ja  .L13 
     cmpq $1, %rax 
     je  .L14 
     testq %rax, %rax 
     jne  .L15 
.L6: 
     movq 8(%rsp), %rax 
     movq (%rbx), %rdx 
     movq %rax, 8(%rbx) 
     movb $0, (%rdx,%rax) 
     addq $24, %rsp 
     popq %rbx 
     popq %rbp 
     popq %r12 
     popq %r13 
     ret 
.L13: 
     leaq 8(%rsp), %rsi 
     xorl %edx, %edx 
     movq %rbx, %rdi 
     call std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_create(unsigned long&, unsigned long) 
     movq 8(%rsp), %rdx 
     movq %rax, (%rbx) 
     movq %rax, %rdi 
     movq %rdx, 16(%rbx) 
.L4: 
     movq %rbp, %rdx 
     movq %r13, %rsi 
     call memcpy 
     jmp  .L6 
.L14: 
     movzbl 0(%r13), %eax 
     movb %al, 16(%rbx) 
     jmp  .L6 
.L2: 
     movl $.LC0, %edi 
     call std::__throw_logic_error(char const*) 
.L15: 
     movq %r12, %rdi 
     jmp  .L4 
foo::foo(int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >): 
     pushq %r15 
     pushq %r14 
     leaq 32(%rdi), %r14 
     pushq %r13 
     pushq %r12 
     leaq 48(%rdi), %r12 
     pushq %rbp 
     pushq %rbx 
     movl %esi, %r15d 
     movq %rdi, %rbx 
     movq %rcx, %r13 
     movq %r8, %rbp 
     subq $104, %rsp 
     movq %r14, 16(%rdi) 
     movq $0, 24(%rdi) 
     leaq 80(%rsp), %rax 
     movq %rdx, 8(%rsp) 
     leaq 32(%rsp), %rsi 
     leaq 64(%rsp), %rdx 
     movb $0, 32(%rdi) 
     movq %r12, %rdi 
     movq %rax, 64(%rsp) 
     leaq 48(%rsp), %rax 
     movsd %xmm0, (%rsp) 
     movq $0, 72(%rsp) 
     movb $0, 80(%rsp) 
     movq %rax, 32(%rsp) 
     movq $0, 40(%rsp) 
     movb $0, 48(%rsp) 
     call bar::bar(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) 
     movq 32(%rsp), %rdi 
     leaq 48(%rsp), %rax 
     cmpq %rax, %rdi 
     je  .L17 
     call operator delete(void*) 
.L17: 
     movq 64(%rsp), %rdi 
     leaq 80(%rsp), %rax 
     cmpq %rax, %rdi 
     je  .L18 
     call operator delete(void*) 
.L18: 
     movsd (%rsp), %xmm1 
     movq 8(%rsp), %rsi 
     leaq 16(%rbx), %rdi 
     movl %r15d, (%rbx) 
     movsd %xmm1, 8(%rbx) 
     call std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_assign(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) 
     movq 0(%rbp), %r15 
     leaq 80(%rsp), %rax 
     movq 8(%rbp), %rbp 
     movq %rax, 64(%rsp) 
     movq %r15, %rax 
     addq %rbp, %rax 
     je  .L21 
     testq %r15, %r15 
     jne  .L21 
     movl $.LC0, %edi 
     call std::__throw_logic_error(char const*) 
.L21: 
     cmpq $15, %rbp 
     movq %rbp, 16(%rsp) 
     ja  .L69 
     cmpq $1, %rbp 
     je  .L70 
     xorl %edx, %edx 
     testq %rbp, %rbp 
     leaq 80(%rsp), %rax 
     jne  .L71 
.L24: 
     movq %rdx, 72(%rsp) 
     movb $0, (%rax,%rdx) 
     leaq 48(%rsp), %rax 
     movq 0(%r13), %r15 
     movq 8(%r13), %rbp 
     movq %rax, 32(%rsp) 
     movq %r15, %rax 
     addq %rbp, %rax 
     je  .L27 
     testq %r15, %r15 
     jne  .L27 
     movl $.LC0, %edi 
     call std::__throw_logic_error(char const*) 
.L27: 
     cmpq $15, %rbp 
     movq %rbp, 24(%rsp) 
     ja  .L72 
     cmpq $1, %rbp 
     je  .L73 
     xorl %eax, %eax 
     testq %rbp, %rbp 
     leaq 48(%rsp), %rdx 
     leaq 24(%rsp), %r13 
     jne  .L74 
.L30: 
     movq %rax, 40(%rsp) 
     leaq 32(%rsp), %rsi 
     movb $0, (%rdx,%rax) 
     leaq 64(%rsp), %rdx 
     movq %r13, %rdi 
     call bar::bar(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) 
     movq %r13, %rsi 
     movq %r12, %rdi 
     call bar::operator=(bar&&) 
     movq 32(%rsp), %rdi 
     leaq 48(%rsp), %rax 
     cmpq %rax, %rdi 
     je  .L31 
     call operator delete(void*) 
.L31: 
     movq 64(%rsp), %rdi 
     leaq 80(%rsp), %rax 
     cmpq %rax, %rdi 
     je  .L16 
     call operator delete(void*) 
.L16: 
     addq $104, %rsp 
     popq %rbx 
     popq %rbp 
     popq %r12 
     popq %r13 
     popq %r14 
     popq %r15 
     ret 
.L69: 
     leaq 16(%rsp), %rsi 
     leaq 64(%rsp), %rdi 
     xorl %edx, %edx 
     call std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_create(unsigned long&, unsigned long) 
     movq 16(%rsp), %rdx 
     movq %rax, 64(%rsp) 
     movq %rax, %rdi 
     movq %rdx, 80(%rsp) 
.L22: 
     movq %rbp, %rdx 
     movq %r15, %rsi 
     call memcpy 
     movq 16(%rsp), %rdx 
     movq 64(%rsp), %rax 
     jmp  .L24 
.L72: 
     leaq 24(%rsp), %r13 
     leaq 32(%rsp), %rdi 
     xorl %edx, %edx 
     movq %r13, %rsi 
     call std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_create(unsigned long&, unsigned long) 
     movq 24(%rsp), %rdx 
     movq %rax, 32(%rsp) 
     movq %rax, %rdi 
     movq %rdx, 48(%rsp) 
.L28: 
     movq %rbp, %rdx 
     movq %r15, %rsi 
     call memcpy 
     movq 24(%rsp), %rax 
     movq 32(%rsp), %rdx 
     jmp  .L30 
.L70: 
     movzbl (%r15), %eax 
     movl $1, %edx 
     movb %al, 80(%rsp) 
     leaq 80(%rsp), %rax 
     jmp  .L24 
.L73: 
     movzbl (%r15), %eax 
     leaq 48(%rsp), %rdx 
     leaq 24(%rsp), %r13 
     movb %al, 48(%rsp) 
     movl $1, %eax 
     jmp  .L30 
     movq %rax, %rbp 
     jmp  .L36 
     movq %rax, %rbp 
     jmp  .L39 
.L74: 
     leaq 48(%rsp), %rdi 
     leaq 24(%rsp), %r13 
     jmp  .L28 
.L71: 
     movq %rax, %rdi 
     jmp  .L22 
.L66: 
     movq %rax, %rbp 
     movq 32(%rsp), %rdi 
     leaq 48(%rsp), %rax 
     cmpq %rax, %rdi 
     je  .L39 
     call operator delete(void*) 
.L39: 
     movq 64(%rsp), %rdi 
     leaq 80(%rsp), %rax 
     cmpq %rax, %rdi 
     je  .L36 
     call operator delete(void*) 
.L36: 
     movq 16(%rbx), %rdi 
     cmpq %rdi, %r14 
     je  .L41 
     call operator delete(void*) 
.L41: 
     movq %rbp, %rdi 
     call _Unwind_Resume 
     jmp  .L66 
foo2::foo2(int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >): 
     pushq %r12 
     pushq %rbp 
     leaq 32(%rdi), %rbp 
     pushq %rbx 
     leaq 16(%rdx), %rax 
     movq %rdi, %rbx 
     subq $64, %rsp 
     movl %esi, (%rdi) 
     movq %rbp, 16(%rdi) 
     movq (%rdx), %rsi 
     movsd %xmm0, 8(%rdi) 
     cmpq %rax, %rsi 
     je  .L90 
     movq %rsi, 16(%rdi) 
     movq 16(%rdx), %rsi 
     movq %rsi, 32(%rdi) 
.L77: 
     movq 8(%rdx), %rsi 
     movq %rsi, 24(%rbx) 
     movq %rax, (%rdx) 
     leaq 48(%rsp), %rax 
     movq $0, 8(%rdx) 
     movb $0, 16(%rdx) 
     movq (%r8), %rdx 
     movq %rax, 32(%rsp) 
     leaq 16(%r8), %rax 
     cmpq %rax, %rdx 
     je  .L91 
     movq %rdx, 32(%rsp) 
     movq 16(%r8), %rdx 
     movq %rdx, 48(%rsp) 
.L79: 
     movq 8(%r8), %rdx 
     movq %rax, (%r8) 
     leaq 16(%rsp), %rax 
     movq $0, 8(%r8) 
     movb $0, 16(%r8) 
     movq %rax, (%rsp) 
     leaq 16(%rcx), %rax 
     movq %rdx, 40(%rsp) 
     movq (%rcx), %rdx 
     cmpq %rdx, %rax 
     je  .L92 
     movq %rdx, (%rsp) 
     movq 16(%rcx), %rdx 
     movq %rdx, 16(%rsp) 
.L81: 
     movq 8(%rcx), %rdx 
     leaq 48(%rbx), %rdi 
     movq %rax, (%rcx) 
     movq $0, 8(%rcx) 
     movb $0, 16(%rcx) 
     movq %rsp, %rsi 
     movq %rdx, 8(%rsp) 
     leaq 32(%rsp), %rdx 
     call bar::bar(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) 
     movq (%rsp), %rdi 
     leaq 16(%rsp), %rax 
     cmpq %rax, %rdi 
     je  .L82 
     call operator delete(void*) 
.L82: 
     movq 32(%rsp), %rdi 
     leaq 48(%rsp), %rax 
     cmpq %rax, %rdi 
     je  .L75 
     call operator delete(void*) 
.L75: 
     addq $64, %rsp 
     popq %rbx 
     popq %rbp 
     popq %r12 
     ret 
.L90: 
     movq 16(%rdx), %rsi 
     movq 24(%rdx), %rdi 
     movq %rsi, 32(%rbx) 
     movq %rdi, 40(%rbx) 
     jmp  .L77 
.L91: 
     movq 16(%r8), %rsi 
     movq 24(%r8), %rdi 
     movq %rsi, 48(%rsp) 
     movq %rdi, 56(%rsp) 
     jmp  .L79 
.L92: 
     movq 16(%rcx), %rsi 
     movq 24(%rcx), %rdi 
     movq %rsi, 16(%rsp) 
     movq %rdi, 24(%rsp) 
     jmp  .L81 
     movq %rax, %r12 
     movq (%rsp), %rdi 
     leaq 16(%rsp), %rax 
     cmpq %rax, %rdi 
     je  .L85 
     call operator delete(void*) 
.L85: 
     movq 32(%rsp), %rdi 
     leaq 48(%rsp), %rax 
     cmpq %rax, %rdi 
     je  .L86 
     call operator delete(void*) 
.L86: 
     movq 16(%rbx), %rdi 
     cmpq %rdi, %rbp 
     je  .L87 
     call operator delete(void*) 
.L87: 
     movq %r12, %rdi 
     call _Unwind_Resume 
.LC4: 
     .string "bar" 
.LC5: 
     .string "foo" 
.LC6: 
     .string "hello" 
main: 
     pushq %rbx 
     movl $.LC4, %esi 
     subq $224, %rsp 
     leaq 160(%rsp), %rdi 
     call std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) [clone .isra.16] 
     leaq 64(%rsp), %rdi 
     movl $.LC5, %esi 
     call std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) [clone .isra.16] 
     leaq 32(%rsp), %rdi 
     movl $.LC6, %esi 
     call std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) [clone .isra.16] 
     leaq 160(%rsp), %r8 
     leaq 64(%rsp), %rcx 
     leaq 32(%rsp), %rdx 
     movsd .LC7(%rip), %xmm0 
     leaq 96(%rsp), %rdi 
     movl $45, %esi 
     call foo::foo(int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) 
     movq 32(%rsp), %rdi 
     leaq 48(%rsp), %rax 
     cmpq %rax, %rdi 
     je  .L94 
     call operator delete(void*) 
.L94: 
     movq 64(%rsp), %rdi 
     leaq 80(%rsp), %rax 
     cmpq %rax, %rdi 
     je  .L95 
     call operator delete(void*) 
.L95: 
     movq 160(%rsp), %rdi 
     leaq 176(%rsp), %rax 
     cmpq %rax, %rdi 
     je  .L96 
     call operator delete(void*) 
.L96: 
     leaq 64(%rsp), %rdi 
     movl $.LC4, %esi 
     call std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) [clone .isra.16] 
     leaq 32(%rsp), %rdi 
     movl $.LC5, %esi 
     call std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) [clone .isra.16] 
     movl $.LC6, %esi 
     movq %rsp, %rdi 
     call std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) [clone .isra.16] 
     leaq 64(%rsp), %r8 
     leaq 32(%rsp), %rcx 
     leaq 160(%rsp), %rdi 
     movsd .LC7(%rip), %xmm0 
     movq %rsp, %rdx 
     movl $45, %esi 
     call foo2::foo2(int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) 
     movq (%rsp), %rdi 
     leaq 16(%rsp), %rax 
     cmpq %rax, %rdi 
     je  .L97 
     call operator delete(void*) 
.L97: 
     movq 32(%rsp), %rdi 
     leaq 48(%rsp), %rax 
     cmpq %rax, %rdi 
     je  .L98 
     call operator delete(void*) 
.L98: 
     movq 64(%rsp), %rdi 
     leaq 80(%rsp), %rax 
     cmpq %rax, %rdi 
     je  .L99 
     call operator delete(void*) 
.L99: 
     movq 176(%rsp), %rdi 
     leaq 192(%rsp), %rax 
     cmpq %rax, %rdi 
     je  .L100 
     call operator delete(void*) 
.L100: 
     movq 112(%rsp), %rdi 
     leaq 128(%rsp), %rax 
     cmpq %rax, %rdi 
     je  .L123 
     call operator delete(void*) 
.L123: 
     addq $224, %rsp 
     xorl %eax, %eax 
     popq %rbx 
     ret 
     movq %rax, %rbx 
.L106: 
     movq 160(%rsp), %rdi 
     leaq 176(%rsp), %rdx 
     cmpq %rdx, %rdi 
     je  .L115 
.L125: 
     call operator delete(void*) 
.L115: 
     movq %rbx, %rdi 
     call _Unwind_Resume 
     movq (%rsp), %rdi 
     leaq 16(%rsp), %rdx 
     movq %rax, %rbx 
     cmpq %rdx, %rdi 
     je  .L110 
     call operator delete(void*) 
.L110: 
     movq 32(%rsp), %rdi 
     leaq 48(%rsp), %rdx 
     cmpq %rdx, %rdi 
     je  .L112 
     call operator delete(void*) 
.L112: 
     movq 64(%rsp), %rdi 
     leaq 80(%rsp), %rdx 
     cmpq %rdx, %rdi 
     je  .L114 
     call operator delete(void*) 
.L114: 
     movq 112(%rsp), %rdi 
     leaq 128(%rsp), %rdx 
     cmpq %rdx, %rdi 
     jne  .L125 
     jmp  .L115 
     movq %rax, %rbx 
     jmp  .L110 
     movq %rax, %rbx 
     jmp  .L112 
     movq %rax, %rbx 
     jmp  .L114 
     movq 32(%rsp), %rdi 
     leaq 48(%rsp), %rdx 
     movq %rax, %rbx 
     cmpq %rdx, %rdi 
     je  .L104 
     call operator delete(void*) 
.L104: 
     movq 64(%rsp), %rdi 
     leaq 80(%rsp), %rdx 
     cmpq %rdx, %rdi 
     je  .L106 
     call operator delete(void*) 
     jmp  .L106 
     movq %rax, %rbx 
     jmp  .L104 
.LC7: 
     .long 1717986918 
     .long 1076389478 
関連する問題