Код с использованием noexcept.
//hello.cpp
class A{
public:
A(){}
~A(){}
};
void fun() noexcept{ //c++11 style
A a[10];
}
int main()
{
fun();
}
Код с использованием throw() .
//hello1.cpp
class A{
public:
A(){}
~A(){}
};
void fun() throw(){//c++98 style
A a[10];
}
int main()
{
fun();
}
Согласно различным онлайн-ссылкам и книге Скотта Мейера, если во время выполнения исключение покидает забаву, спецификация исключений забавы нарушается. В спецификации исключений C++98 стек вызовов раскручивается до вызывающего объекта f, и после некоторых действий, не имеющих отношения к данному случаю, выполнение программы прекращается. Со спецификацией исключений C++11 поведение во время выполнения немного отличается: стек, возможно, раскручивается только до завершения выполнения программы. Он сказал, что код, использующий noexcept, более оптимизирован, чем код, использующий throw().
Но когда я сгенерировал машинный код для вышеуказанной программы, я обнаружил, что код, сгенерированный для обоих случаев, абсолютно одинаков.
$ g++ --std=c++11 hello1.cpp -O0 -S -o throw1.s
$ g++ --std=c++11 hello.cpp -O0 -S -o throw.s
диф ниже.
$ diff throw.s throw1.s
1c1
< .file "hello.cpp"
---
> .file "hello1.cpp"
Сгенерированный машинный код показан ниже для функции fun для обоих случаев.
.LFB1202:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
pushq %r12
pushq %rbx
subq $16, %rsp
.cfi_offset 12, -24
.cfi_offset 3, -32
leaq -32(%rbp), %rax
movl $9, %ebx
movq %rax, %r12
jmp .L5
.L6:
movq %r12, %rdi
call _ZN1AC1Ev
addq $1, %r12
subq $1, %rbx
.L5:
cmpq $-1, %rbx
jne .L6
leaq -32(%rbp), %rbx
addq $10, %rbx
.L8:
leaq -32(%rbp), %rax
cmpq %rax, %rbx
je .L4
subq $1, %rbx
movq %rbx, %rdi
call _ZN1AD1Ev
jmp .L8
.L4:
addq $16, %rsp
popq %rbx
popq %r12
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1202:
.size _Z3funv, .-_Z3funv
.globl main
.type main, @function
В чем преимущество использования noexcept, когда noexcept и throw генерируют один и тот же код?
fun()
и посмотрите, изменит ли это что-нибудь. Компилятор, безусловно, может обнаружить, что в вашем коде не генерируется исключение, а это означает, что нет ни фактической необходимости (C++98), ни потенциальной необходимости (C++11) раскручивать стек. - person Peter   schedule 19.01.2016int main(){}
. Вы должны найти способ (скажем, бросить в зависимости от пользовательского ввода - вы идете и вызываетеnew
unguarded с количеством байтов, определенным пользователем), чтобы предотвратить такие оптимизации, в то же время допуская некоторые из них. - person Yakk - Adam Nevraumont   schedule 19.01.2016