मैं निम्नलिखित कोड आदेश g++ -std=c++11 t.cpp
का उपयोग कर संकलन:क्या सी ++ 11 बल बिना शर्त के चलता है?
#include <vector>
#include <cstring> //memcpy()
class s
{
char *p;
size_t size;
public:
s(){
size=10;
p=new char[size];
}
s(const s &other){
size=other.size;
p=new char[size];
memcpy(p,other.p,other.size);
}
~s(){ delete [] p; }
};
int main()
{
std::vector<s> ss;
ss.push_back(s());
}
यह gdb
लॉग है:
Breakpoint 1, main() at t.cpp:23
23 ss.push_back(s());
s::s (this=0x7fffffffe370) at t.cpp:9
9 size=10;
10 p=new char[size];
11 }
std::vector<s, std::allocator<s> >::push_back(s&&) (this=0x7fffffffe350,
__x=<unknown type in /tmp/a.out, CU 0x0, DIE 0x20d0>)
at /usr/include/c++/4.9/bits/stl_vector.h:932
932 { emplace_back(std::move(__x)); }
std::move<s&> (__t=...) at /usr/include/c++/4.9/bits/move.h:102
102 { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
std::vector<s, std::allocator<s> >::emplace_back<s>(s&&) (this=0x7fffffffe350)
at /usr/include/c++/4.9/bits/vector.tcc:94
94 if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
101 _M_emplace_back_aux(std::forward<_Args>(__args)...);
102 }
s::~s (this=0x7fffffffe370, __in_chrg=<optimized out>) at t.cpp:17
17 ~s(){ delete [] p; }
std::vector<s, std::allocator<s> >::~vector (this=0x7fffffffe350, __in_chrg=<optimized out>)
at /usr/include/c++/4.9/bits/stl_vector.h:425
लॉग से, मैं निम्नलिखित प्रभाव में हूं:
- जीसीसी पर ध्यान नहीं देता प्रतिलिपि निर्माता
s(const s &other)
। जीसीसी स्वचालित रूप से
:class s
के लिए एकmove
निर्माता बनाता है और फिरstd::vector.push_back()
कॉलmove
निर्माता।This article राज्यों
इस प्रकार, यदि क्लास सी की परिभाषा को स्पष्ट रूप से एक कदम असाइनमेंट ऑपरेटर की घोषणा नहीं करता है, एक परोक्ष घोषित रूप में चूक ही अगर निम्न स्थितियों में मुलाकात कर रहे हैं के सभी हो जाएगा
मेरे यहाँ सवाल
class s
जाहिरा तौर पर, एक उपयोगकर्ता के घोषित नाशक~s()
है जिसका अर्थ हैclass s
आगे शर्त को पूरा नहीं करता है और इस तरह जीसीसीstd::vector.push_back()
परmove
लागू नहीं करना चाहिए। जीसीसी कैसे व्यवहार करता है?नाशक
~s()
दो बार कहा जाता है: पहले तुरंत अस्थायीs()
के बादss.push_back(s());
को तर्क के रूप में पारित कर दिया गया है और ले जाया गया है, और दूसराstd::vector<s>
का नाशक कहा जाता है के बाद।- क्योंकि यह कोड rule of three से मेल नहीं खाता है, इसलिए
std::vector<s>
के विनाशक को क्रैश होने पर यह दुर्घटनाग्रस्त हो जाता है। ऑब्जेक्टs
मेंp
द्वारा इंगित सामग्री पहले~s()
द्वारा पहले ही हटा दी गई है। इसलिए,std::vector<s>
~s()
को नष्ट करने वाले विनाशक कोdouble free or corruption
जैसे त्रुटि से क्रैश होना चाहिए।
हालांकि, मेरे आश्चर्य के लिए, किसी भी तरह से यह प्रोग्राम सामान्य रूप से चलता है और समाप्त हो जाता है।
प्रश्न 1: प्रोग्राम क्यों क्रैश नहीं होता है? क्या मैं बस भाग्यशाली हूं?
प्रश्न 2: gdb
लॉग के अनुसार, इसका मतलब यह है कि पहले सी ++ 11 बैठक rule of three
लेकिन rule of five बैठक नहीं, तो इस उदाहरण की तरह के लिए बनाया गया कोड, बहुत जब वे सेल्सियस के लिए संकलित किया गया है दुर्घटना की संभावना है ++ 11 निष्पादन योग्य?
संपादित:
यह सवाल इस तरह के gdb
संदेशों के मेरी अशुद्ध अर्थ के कारण उठाया गया था:
std::vector<s, std::allocator<s> >::push_back(s&&)
emplace_back(std::move(__x));
std::vector<s, std::allocator<s> >::emplace_back<s>(s&&)
जो मुझे नेतृत्व कि जीसीसी एक चाल निर्माता बनाता है सोचने के लिए।मैंने अभी तक इन विशेषज्ञों को बताया है - s(const s &other)
में ब्रेक पॉइंट सेट करना, और ध्यान दिया कि कार्यक्रम वहां रुक गया है। यह खोज मेरे सभी सवालों को अमान्य कर देती है।
जैसा कि यहां हर विशेषज्ञ ने सुझाव दिया है, तथ्यों हैं: 1. जीसीसी कोई भी चालक कन्स्ट्रक्टर नहीं बनाता है। 2. मौजूदा प्रतिलिपि निर्माता को बुलाया जाता है।
बड़ी मदद के लिए सभी को धन्यवाद!
कॉपी कन्स्ट्रक्टर में ब्रेकपॉइंट डालने का प्रयास करें। क्या कार्यक्रम उस ब्रेकपॉइंट पर रुकता है? –
यह 'पुश_बैक' नए तत्व को आरंभ करने के लिए आंतरिक रूप से 'std :: move' नामक फ़ंक्शन को कॉल करता है, लेकिन यह प्रारंभिक प्रतिलिपि बनानेवाला का उपयोग करता है (क्योंकि कोई चालक कन्स्ट्रक्टर नहीं है और कॉपी कन्स्ट्रक्टर सबसे अच्छा मिलान है)। कोई चालक कन्स्ट्रक्टर उत्पन्न या बुलाया नहीं जाता है। – cpplearner
@ Somprogrammerdude मैंने अभी किया था। हां, कार्यक्रम कॉपी कन्स्ट्रक्टर में बंद हो जाता है। –