अन्य लोगों ने पहले से ही अन्य मुद्दों को संबोधित किया है, इसलिए मैं सिर्फ एक बिंदु को देखूंगा: क्या आप कभी किसी ऑब्जेक्ट को मैन्युअल रूप से हटाना चाहते हैं।
इसका जवाब है हाँ। @DavidSchwartz ने एक उदाहरण दिया, लेकिन यह काफी असामान्य है। मैं एक उदाहरण देता हूँ जो कि C ++ प्रोग्रामर के बहुत सारे समय के उपयोग के घेरे में है: std::vector
(और std::deque
, हालाँकि इसका उपयोग बहुत अधिक नहीं किया गया है)।
जैसा कि ज्यादातर लोग जानते हैं, std::vector
स्मृति का एक बड़ा ब्लॉक आवंटित करेगा जब / यदि आप अपने वर्तमान आवंटन से अधिक आइटम जोड़ सकते हैं। जब यह ऐसा करता है, हालांकि, इसमें मेमोरी का एक ब्लॉक होता है जो वर्तमान में वेक्टर की तुलना में अधिक वस्तुओं को रखने में सक्षम है ।
यह प्रबंधित करने के लिए कि vector
कवर के तहत क्या होता है , ऑब्जेक्ट के माध्यम से कच्ची मेमोरी आवंटित की जाती Allocator
है (जो, जब तक आप अन्यथा निर्दिष्ट नहीं करते हैं, इसका मतलब है कि यह उपयोग करता है ::operator new
)। फिर, जब आप push_back
किसी आइटम को जोड़ने के लिए (उदाहरण के लिए) उपयोग करते हैं vector
, तो आंतरिक रूप से वेक्टर placement new
अपनी मेमोरी स्पेस के अप्रयुक्त भाग (पहले) में एक आइटम बनाने के लिए उपयोग करता है।
अब, क्या होगा जब / यदि आप erase
वेक्टर से एक आइटम? यह सिर्फ उपयोग नहीं कर सकता है delete
- जो इसकी मेमोरी के पूरे ब्लॉक को रिलीज़ करेगा; किसी भी अन्य को नष्ट किए बिना उस मेमोरी में एक वस्तु को नष्ट करने की आवश्यकता होती है, या किसी भी मेमोरी को ब्लॉक करने से मुक्त करता है जिसे वह नियंत्रित करता है (उदाहरण के लिए, यदि आप erase
एक वेक्टर से 5 आइटम, तो तुरंत push_back
5 और आइटम, यह गारंटी है कि वेक्टर पुनः लोड नहीं करेगा स्मृति जब आप ऐसा करते हैं।
ऐसा करने के लिए, वेक्टर सीधे ऑब्जेक्ट को स्पष्ट रूप से विध्वंसक कहकर स्मृति में नष्ट कर देता है, उपयोग नहीं करके delete
।
हैं, तो हो सकता है, किसी और को एक कंटेनर सन्निहित भंडारण मोटे तौर पर की तरह एक का उपयोग कर लिखने के लिए थे vector
करता है (या कि किसी भिन्न रूप, की तरह std::deque
वास्तव में करता है), तो आप लगभग निश्चित रूप से उसी तकनीक का उपयोग करना चाहते हैं।
उदाहरण के लिए, आइए विचार करें कि आप एक परिपत्र रिंग-बफर के लिए कोड कैसे लिख सकते हैं।
#ifndef CBUFFER_H_INC
#define CBUFFER_H_INC
template <class T>
class circular_buffer {
T *data;
unsigned read_pos;
unsigned write_pos;
unsigned in_use;
const unsigned capacity;
public:
circular_buffer(unsigned size) :
data((T *)operator new(size * sizeof(T))),
read_pos(0),
write_pos(0),
in_use(0),
capacity(size)
{}
void push(T const &t) {
// ensure there's room in buffer:
if (in_use == capacity)
pop();
// construct copy of object in-place into buffer
new(&data[write_pos++]) T(t);
// keep pointer in bounds.
write_pos %= capacity;
++in_use;
}
// return oldest object in queue:
T front() {
return data[read_pos];
}
// remove oldest object from queue:
void pop() {
// destroy the object:
data[read_pos++].~T();
// keep pointer in bounds.
read_pos %= capacity;
--in_use;
}
~circular_buffer() {
// first destroy any content
while (in_use != 0)
pop();
// then release the buffer.
operator delete(data);
}
};
#endif
मानक कंटेनरों के विपरीत, यह उपयोग करता है operator new
और operator delete
सीधे। वास्तविक उपयोग के लिए, आप शायद एक एलोकेटर वर्ग का उपयोग करना चाहते हैं, लेकिन फिलहाल यह योगदान (आईएमओ, वैसे भी) की तुलना में विचलित करने के लिए अधिक होगा।