- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我知道初始化列表相对于普通构造函数体的优势(默认构造后跟赋值,而不是构造)。
我也知道现代编译器的优化能力。
现代编译器是否足够聪明,可以将非初始化列表构造函数优化为前一种类型?如果是,它仅限于基本类型,还是也包括用户定义的类型?如果不是,为什么不呢?
最佳答案
这是 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
关于c++ - 构造函数的编译器优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36724840/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!