Standar ini tidak memerlukan optimasi khusus dalam kasus objek pengecualian yang tidak disebutkan namanya. Sebaliknya, hal ini memerlukan efek seolah-olah salinan sementara diinisialisasi. Penyalinan ini dapat mengakibatkan memori dialokasikan secara dinamis.
N3290 §15.3/16:
Jika deklarasi-pengecualian menentukan nama, ia mendeklarasikan variabel yang diinisialisasi salinan (8.5) dari objek pengecualian. Jika deklarasi-pengecualian menunjukkan tipe objek tetapi tidak menentukan nama, sementara (12.2) akan diinisialisasi salinan (8.5) dari objek pengecualian. Masa hidup variabel atau sementara berakhir ketika handler keluar, setelah penghancuran objek otomatis apa pun yang diinisialisasi dalam handler.
Paragraf di atas tidak menyebutkan penangkapan dengan referensi, sehingga dapat disimpulkan secara masuk akal bahwa hal tersebut berlaku terlepas dari apakah objek pengecualian ditangkap dengan referensi atau tidak; bahwa salinannya tetap dibuat.
Namun hal tersebut bertentangan dengan paragraf berikutnya:
N3290 §15.3/17:
Saat handler mendeklarasikan objek non-konstan, perubahan apa pun pada objek tersebut tidak akan memengaruhi objek sementara yang diinisialisasi dengan eksekusi ekspresi lemparan . Saat handler mendeklarasikan referensi ke objek non-konstan, setiap perubahan pada objek yang direferensikan adalah perubahan pada objek sementara yang diinisialisasi ketika ekspresi lemparan dijalankan dan akan berpengaruh jika objek tersebut dilempar kembali.
Jadi, tipe yang dideklarasikan T&
(dengan T
non-const
) adalah satu-satunya kasus di mana C++11 memerlukan referensi langsung ke objek yang dilempar, alih-alih menyalin. Dan hal yang sama juga terjadi pada C++03, hanya saja C++03 memiliki beberapa kata tambahan tentang optimasi as-if. Jadi, untuk yang formal sebaiknya diutamakan
catch( T& name )
Dan
catch( T& )
Namun, saya selalu menemukan pengecualian seperti catch( T const& )
. Dari sudut pandang praktis seseorang dapat berasumsi bahwa kompiler akan mengoptimalkannya ke referensi langsung ke objek yang dilempar, meskipun ada kemungkinan untuk merancang kasus di mana efek program yang diamati akan menjadi non-standar. Misalnya <evil grin>
#include <stdio.h>
#include <stdexcept>
struct Error
: std::runtime_error
{
public:
static Error* pThrown;
char const* pMessage_;
Error()
: std::runtime_error( "Base class message" )
, pMessage_( "Original message." )
{
printf( "Default-construction of Error object.\n" );
pThrown = this;
}
Error( Error const& other )
: std::runtime_error( other )
, pMessage_( other.pMessage_ )
{
printf( "Copy-construction of Error obejct.\n" );
}
char const* what() const throw() { return pMessage_; }
};
Error* Error::pThrown = 0;
int main()
{
printf( "Testing non-const ref:\n" );
try
{
throw Error();
}
catch( Error& x )
{
Error::pThrown->pMessage_ = "Modified message.";
printf( "%s\n", x.what() );
}
printf( "\n" );
printf( "Testing const ref:\n" );
try
{
throw Error();
}
catch( Error const& x )
{
Error::pThrown->pMessage_ = "Modified message";
printf( "%s\n", x.what() );
}
}
Dengan MinGW g++ 4.4.1 dan Visual C++ 10.0, hasilnya adalah
Testing non-const ref:
Default-construction of Error object.
Modified message.
Testing const ref:
Default-construction of Error object.
Modified message
Seorang formalis yang bertele-tele mungkin mengatakan bahwa kedua kompiler tidak sesuai, gagal membuat salinan untuk kasus Error const&
. Seorang praktisi yang murni praktis mungkin berkata, hei, apa lagi yang Anda harapkan? Dan menurut saya, kata-kata dalam standar sangat jauh dari sempurna di sini, dan jika ada, kita harus mengharapkan klarifikasi untuk secara eksplisit mengizinkan keluaran di atas, sehingga penangkapan dengan referensi ke const
juga aman dan efisien secara maksimal.
Kesimpulannya. pertanyaan OP:
Menangkap dengan referensi tidak akan memanggil konstruktor salinan yang berpotensi menghentikan program.
Standar ini hanya menjamin hal ini untuk referensi ke non-const
.
Dalam praktiknya, seperti yang ditunjukkan, hal ini juga dijamin untuk referensi ke const
, bahkan ketika hasil program terpengaruh.
Salam & hth.,
person
Cheers and hth. - Alf
schedule
13.09.2011
my_exception&
merupakan praktik standar, saya menemukan bahwa sebagian besar pengecualian tidak diubah, dan oleh karena itu akan lebih baik untuk menangkapmy_exception const&
. Perhatikan bahwawhat
adalahconst
. - person Matthieu M.   schedule 13.09.2011