Ini adalah kode contoh saya:
#include <iostream>
#include <string>
using namespace std;
class MyClass
{
string figName;
public:
MyClass(const string& s)
{
figName = s;
}
const string& getName() const
{
return figName;
}
};
ostream& operator<<(ostream& ausgabe, const MyClass& f)
{
ausgabe << f.getName();
return ausgabe;
}
int main()
{
MyClass f1("Hello");
cout << f1;
return 0;
}
Jika saya berkomentar, #include <string>
saya tidak mendapatkan kesalahan kompiler, saya kira karena itu semacam dimasukkan melalui #include <iostream>
. Jika saya "mengklik kanan -> Go to Definition" di Microsoft VS, keduanya mengarah ke baris yang sama di xstring
file:
typedef basic_string<char, char_traits<char>, allocator<char> >
string;
Tetapi ketika saya menjalankan program saya, saya mendapatkan kesalahan pengecualian:
0x77846B6E (ntdll.dll) di OperatorString.exe: 0xC00000FD: Stack overflow (Parameter: 0x00000001, 0x01202FC4)
Adakah ide mengapa saya mendapatkan error runtime saat berkomentar #include <string>
? Saya menggunakan VS 2013 Express.
c++
string
stack-overflow
explicit
di udara
sumber
sumber
#include<iostream>
dan<string>
mungkin keduanya termasuk<common/stringimpl.h>
....\main.cpp(23) : warning C4717: 'operator<<': recursive on all control paths, function will cause runtime stack overflow
dengan menjalankan baris inicl /EHsc main.cpp /Fetest.exe
Jawaban:
Sungguh, perilaku yang sangat menarik.
Dengan kompiler MS VC ++ kesalahan terjadi karena jika Anda tidak melakukannya,
#include <string>
Anda tidak akanoperator<<
menentukan untukstd::string
.Ketika kompilator mencoba untuk mengkompilasi,
ausgabe << f.getName();
ia mencari yangoperator<<
didefinisikan untukstd::string
. Karena tidak ditentukan, kompilator mencari alternatif. Ada yangoperator<<
didefinisikan untukMyClass
dan kompilator mencoba menggunakannya, dan untuk menggunakannya ia harus mengonversistd::string
keMyClass
dan inilah yang terjadi karenaMyClass
memiliki konstruktor non-eksplisit! Jadi, kompilator akhirnya membuat instance baru dari AndaMyClass
dan mencoba mengalirkannya lagi ke aliran keluaran Anda. Ini menghasilkan rekursi tanpa akhir:Untuk menghindari kesalahan, Anda perlu
#include <string>
memastikan bahwa ada yangoperator<<
ditentukan untukstd::string
. Anda juga harus membuatMyClass
konstruktor Anda eksplisit untuk menghindari jenis konversi tak terduga ini. Aturan kebijaksanaan: buat konstruktor eksplisit jika mereka hanya mengambil satu argumen untuk menghindari konversi implisit:Sepertinya
operator<<
untukstd::string
mendapat didefinisikan hanya ketika<string>
disertakan (dengan compiler MS) dan untuk alasan itu semuanya mengkompilasi, namun Anda mendapatkan perilaku agak tak terduga sepertioperator<<
semakin disebut rekursif untukMyClass
bukan memanggiloperator<<
untukstd::string
.Tidak, string disertakan sepenuhnya, jika tidak, Anda tidak akan dapat menggunakannya.
sumber
std::string
tanpa#include<string>
segala macam hal dapat terjadi, tidak terbatas pada kesalahan waktu kompilasi. Memanggil fungsi atau operator yang salah tampaknya merupakan pilihan lain.Masalahnya adalah kode Anda melakukan rekursi tak terbatas. Operator streaming untuk
std::string
(std::ostream& operator<<(std::ostream&, const std::string&)
) dideklarasikan dalam<string>
file header, meskipunstd::string
itu sendiri dideklarasikan di file header lain (disertakan oleh<iostream>
dan<string>
).Ketika Anda tidak menyertakan
<string>
kompilator mencoba menemukan cara untuk mengkompilasiausgabe << f.getName();
.Kebetulan Anda telah menentukan operator streaming untuk
MyClass
dan konstruktor yang mengakui astd::string
, sehingga compiler menggunakannya (melalui konstruksi implisit ), membuat panggilan rekursif.Jika Anda mendeklarasikan
explicit
konstruktor (explicit MyClass(const std::string& s)
) maka kode Anda tidak akan dikompilasi lagi, karena tidak ada cara untuk memanggil operator streaming denganstd::string
, dan Anda akan dipaksa untuk menyertakan<string>
header.EDIT
Lingkungan pengujian saya adalah VS 2010, dan mulai dari tingkat peringatan 1 (
/W1
) ini memperingatkan Anda tentang masalah:sumber