බහුලව භාවිතා වන මතක විබෙදුම් ක්රම දෙකක් තිබේ: ස්වයංක්රීය වෙන් කිරීම සහ ගතික වෙන් කිරීම. පොදුවේ ගත් කල, එක් එක් සඳහා අනුරූප කලාපයක් ඇත: තොගය සහ ගොඩ.
සිරස්
තොගය සෑම විටම අනුපිළිවෙලින් මතකය වෙන් කරයි. එය එසේ කළ හැක්කේ ඔබට ප්රතිලෝම අනුපිළිවෙලින් මතකය මුදා හැරීමට අවශ්ය නිසාය (පළමු, අවසාන, අවසන්: FILO). බොහෝ ක්රමලේඛන භාෂාවල දේශීය විචල්යයන් සඳහා මතක වෙන් කිරීමේ තාක්ෂණය මෙයයි. එය ඉතා, ඉතා වේගවත් බැවින් එයට අවම පොත් තැබීමක් අවශ්ය වන අතර වෙන් කිරීම සඳහා ඊළඟ ලිපිනය ව්යංග වේ.
C ++ හි, මෙය ස්වයංක්රීය ආචයනය ලෙස හැඳින්වෙන්නේ විෂය පථය අවසානයේ ගබඩාව ස්වයංක්රීයව හිමිකම් කියන බැවිනි. වත්මන් කේත වාරණය ක්රියාත්මක කිරීම අවසන් වූ වහාම (භාවිතයෙන් වෙන් කිරීම {}), එම කොටසෙහි ඇති සියලුම විචල්යයන් සඳහා මතකය ස්වයංක්රීයව එකතු වේ. සම්පත් පිරිසිදු කිරීම සඳහා විනාශ කරන්නන් කැඳවන මොහොත මෙයයි .
ගොඩවල්
ගොඩවල් වඩාත් නම්යශීලී මතක විබෙදුම් ක්රමයක් සඳහා ඉඩ ලබා දේ. පොත් තැබීම වඩාත් සංකීර්ණ වන අතර ප්රතිපාදන මන්දගාමී වේ. කිසිදු ගම්ය නිදහස් අවස්ථාවක නොමැති නිසා, ඔබ මතක අතින්, භාවිතා නිදහස් කළ යුතුය deleteහෝ delete[]( freeසී.) කෙසේ වෙතත්, සංචිත මුදා හැරීමේ ලක්ෂ්යයක් නොමැතිකම ගොඩවල නම්යශීලීභාවයේ යතුරයි.
ගතික වෙන් කිරීම භාවිතා කිරීමට හේතු
සංචය භාවිතා කිරීම මන්දගාමී වන අතර මතක කාන්දු වීමකට හෝ මතක ඛණ්ඩනයකට තුඩු දිය හැකි වුවද, ගතික වෙන් කිරීම සඳහා හොඳ භාවිත අවස්ථා තිබේ, මන්ද එය සීමිත බැවිනි.
ගතික වෙන් කිරීම භාවිතා කිරීමට ප්රධාන හේතු දෙකක්:
සම්පාදනය කරන වේලාවේදී ඔබට කොපමණ මතකයක් අවශ්යදැයි ඔබ නොදනී. නිදසුනක් ලෙස, පෙළ ගොනුවක් නූලකට කියවන විට, සාමාන්යයෙන් ගොනුවේ ඇති ප්රමාණය ඔබ දන්නේ නැත, එබැවින් ඔබ වැඩසටහන ක්රියාත්මක කරන තෙක් කොපමණ මතකයක් වෙන් කළ යුතුද යන්න තීරණය කළ නොහැක.
වත්මන් බ්ලොක් එකෙන් ඉවත් වූ පසු මතකය වෙන් කිරීමට ඔබට අවශ්යය. උදාහරණයක් ලෙස, string readfile(string path)ගොනුවක අන්තර්ගතය නැවත ලබා දෙන ශ්රිතයක් ලිවීමට ඔබට අවශ්ය විය හැකිය . මෙම අවස්ථාවෙහිදී, තොගයට සම්පූර්ණ ගොනු අන්තර්ගතය රඳවා තබා ගත හැකි වුවද, ඔබට ශ්රිතයකින් ආපසු පැමිණ වෙන් කළ මතක කොටස තබා ගත නොහැක.
ගතික වෙන් කිරීම බොහෝ විට අනවශ්ය වන්නේ ඇයි
සී ++ හි ඩිස්ට්රැක්ටර් නමින් හැඳින්වෙන පිළිවෙලක් තිබේ. මෙම යාන්ත්රණය මඟින් සම්පත් වල ආයු කාලය විචල්යයක ආයු කාලය සමඟ පෙළගැස්වීමෙන් සම්පත් කළමනාකරණය කිරීමට ඉඩ ලබා දේ. මෙම තාක්ෂණය RAII ලෙස හැඳින්වෙන අතර එය C ++ හි කැපී පෙනෙන ලක්ෂ්යය වේ. එය සම්පත් වස්තු තුළට ඔතා. std::stringකදිම නිදසුනකි. මෙම ස්නිපටය:
int main ( int argc, char* argv[] )
{
std::string program(argv[0]);
}
ඇත්ත වශයෙන්ම විචල්ය මතක ප්රමාණයක් වෙන් කරයි. මෙම std::stringවස්තුව ගොඩ ගසා එහි destructor එය නිකුත් භාවිතා මතකයක් වෙන්. මෙම අවස්ථාවේදී, ඔබට කිසිදු සම්පත් අතින් කළමණාකරනය කිරීමට අවශ්ය නොවූ අතර ගතික මතක වෙන්කිරීමේ ප්රතිලාභ තවමත් ලැබුණි.
විශේෂයෙන්, මෙම ස්නිපටයේ එය ඇඟවුම් කරයි:
int main ( int argc, char* argv[] )
{
std::string * program = new std::string(argv[0]); // Bad!
delete program;
}
අනවශ්ය ගතික මතක වෙන් කිරීමක් ඇත. වැඩසටහනට වැඩි ටයිප් කිරීමක් අවශ්ය වේ (!) සහ මතකය අවලංගු කිරීමට අමතක වීමේ අවදානම හඳුන්වා දෙයි. පෙනෙන ප්රතිලාභයක් නොමැතිව එය මෙය කරයි.
ඔබ හැකි සෑම විටම ස්වයංක්රීය ආචයනය භාවිතා කළ යුත්තේ ඇයි
මූලික වශයෙන්, අවසාන ඡේදය එය සාරාංශ කරයි. හැකි සෑම විටම ස්වයංක්රීය ආචයනය භාවිතා කිරීමෙන් ඔබේ වැඩසටහන් සිදු වේ:
- ටයිප් කිරීමට වේගවත්;
- ධාවනය වන විට වේගවත්;
- මතක / සම්පත් කාන්දුවීම් වලට ඇති ඉඩකඩ අඩුය.
ප්රසාද ලකුණු
යොමු කරන ලද ප්රශ්නයේ දී, අතිරේක ගැටළු තිබේ. විශේෂයෙන්, පහත පන්තිය:
class Line {
public:
Line();
~Line();
std::string* mString;
};
Line::Line() {
mString = new std::string("foo_bar");
}
Line::~Line() {
delete mString;
}
ඇත්ත වශයෙන්ම පහත දැක්වෙන ඒවාට වඩා භාවිතා කිරීම වඩා අවදානම් සහිත ය:
class Line {
public:
Line();
std::string mString;
};
Line::Line() {
mString = "foo_bar";
// note: there is a cleaner way to write this.
}
හේතුව std::stringපිටපත් සාදන්නෙකු නිසියාකාරව නිර්වචනය කිරීමයි. පහත වැඩසටහන සලකා බලන්න:
int main ()
{
Line l1;
Line l2 = l1;
}
මුල් අනුවාදය භාවිතා කරමින්, මෙම වැඩසටහන deleteඑකම නූලක දෙවරක් භාවිතා කරන බැවින් එය බිඳ වැටෙනු ඇත . නවීකරණය කරන ලද අනුවාදය භාවිතා කරමින්, එක් එක් අවස්ථාවට Lineතමන්ගේම සංගීත නිදසුනක් හිමි වන අතර , සෑම එකක්ම තමන්ගේම මතකයක් ඇති අතර දෙකම වැඩසටහන අවසානයේ මුදා හරිනු ඇත.
වෙනත් සටහන්
ඉහත සියලු හේතු නිසා RAII හි පුළුල් භාවිතය C ++ හි හොඳම භාවිතයක් ලෙස සැලකේ. කෙසේ වෙතත්, අතිරේක ප්රතිලාභයක් ඇති අතර එය ක්ෂණිකව නොපෙනේ. මූලික වශයෙන්, එය එහි කොටස්වල එකතුවට වඩා හොඳයි. සමස්ත යාන්ත්රණයම සංයුක්ත වේ. එය පරිමාණය කරයි.
ඔබ Lineගොඩනැඟිලි අංගයක් ලෙස පන්තිය භාවිතා කරන්නේ නම් :
class Table
{
Line borders[4];
};
ඉන්පසු
int main ()
{
Table table;
}
std::stringඅවස්ථා හතරක්, අවස්ථා හතරක් Line, එක් Tableඅවස්ථාවක් සහ සියලු නූල්වල අන්තර්ගතය වෙන් කරන අතර සියල්ල ස්වයංක්රීයව නිදහස් වේ.