একটি সি ++ ফাংশনে স্থির পরিবর্তনশীলটির আজীবন কত?


373

যদি কোনও ভেরিয়েবলটিকে staticকোনও ফাংশনের স্কোপ হিসাবে ঘোষণা করা হয় তবে এটি কেবল একবার আরম্ভ করা হবে এবং ফাংশন কলগুলির মধ্যে এর মান ধরে রাখবে। এর জীবনকাল ঠিক কী? এর নির্মাতা এবং ধ্বংসকারীকে কখন ডাকা হবে?

void foo() 
{ 
    static string plonk = "When will I die?";
}

উত্তর:


257

ফাংশন staticভেরিয়েবলগুলির আজীবন প্রথমবার শুরু হয় [0] প্রোগ্রাম প্রবাহ ঘোষণার মুখোমুখি হয় এবং এটি প্রোগ্রাম সমাপ্তিতে শেষ হয়। এর অর্থ হল যে রান-টাইমটি অবশ্যই এটি নির্মাণ করা হয়েছে কেবল তখনই এটি ধ্বংস করার জন্য কিছু বই সম্পাদন করতে হবে।

অতিরিক্ত হিসাবে, যেহেতু স্ট্যান্ডার্ডটি বলে যে স্থির বস্তুর ধ্বংসকারীদের অবশ্যই তাদের নির্মাণকাজ সমাপ্তির বিপরীতে চালানো উচিত [1] , এবং নির্মাণের ক্রম নির্দিষ্ট প্রোগ্রামের উপর নির্ভরশীল হতে পারে, তাই নির্মাণের ক্রমটি অবশ্যই বিবেচনায় নেওয়া উচিত ।

উদাহরণ

struct emitter {
    string str;
    emitter(const string& s) : str(s) { cout << "Created " << str << endl; }
    ~emitter() { cout << "Destroyed " << str << endl; }
};

void foo(bool skip_first) 
{
    if (!skip_first)
        static emitter a("in if");
    static emitter b("in foo");
}

int main(int argc, char*[])
{
    foo(argc != 2);
    if (argc == 3)
        foo(false);
}

আউটপুট:

সি:> નમૂના.exe
foo এ তৈরি হয়েছিল ফু- তে
ধ্বংস হয়ে গেছে

সি:> sample.exe 1
নির্মিত যদি
foo বিন্যাস সালে সৃষ্ট তৈরি হয়েছে
foo বিন্যাস ধ্বংস
যদি ধ্বংস

সি:> নমুনা.এক্সএই 2 2
foo এ
তৈরি করা হয়েছে যদি ফু-তে
ধ্বংস হয়ে যায় তবে
ধ্বংস হয়

[0]যেহেতু সি ++ 98 [2] এর একাধিক থ্রেডের কোনও উল্লেখ নেই যে এটি একাধিক থ্রেড পরিবেশে কীভাবে আচরণ করা হবে তা অনির্ধারিত, এবং রডির উল্লেখ করার সাথে সাথে সমস্যা হতে পারে ।

[1] সি ++ 98 বিভাগ 3.6.3.1 [বেসিক.স্টার্ট.মিটার]

[2]সি ++ এ 11 স্ট্যাটিক্সটি থ্রেড নিরাপদ উপায়ে শুরু করা হয়েছে, এটি ম্যাজিক স্ট্যাটিকস নামেও পরিচিত ।


2
সিটর / ডিটোর পার্শ্ব প্রতিক্রিয়াবিহীন সহজ প্রকারের জন্য, এগুলি বিশ্বব্যাপী সরল প্রকারের মতো একই পদ্ধতিতে আরম্ভ করার জন্য একটি সোজাসুজি অপ্টিমাইজেশন। এটি ব্রাঞ্চিং, পতাকা এবং ধ্বংসের ক্রম সম্পর্কিত বিষয়গুলি এড়িয়ে চলে। তাদের জীবদ্দশায় কোনও ভিন্ন কথা বলা যায় না।
জন ম্যাকফার্লেন

1
যদি ফাংশনটিকে একাধিক থ্রেড দ্বারা ডাকা যেতে পারে, তবে এর অর্থ কি এটির নিশ্চিত হওয়া দরকার যে আপনার স্থির ঘোষণাগুলি অবশ্যই সি ++ 98 এ একটি মিউটেক্স দ্বারা সুরক্ষিত করা উচিত ??
অ্যালিওরকোড

1
"গ্লোবাল অবজেক্টগুলির ডেস্ট্রাক্টরদের অবশ্যই তাদের নির্মাণ সমাপ্তির বিপরীতে চালানো উচিত" এখানে প্রযোজ্য নয়, কারণ এই বস্তুগুলি বৈশ্বিক নয়। স্থির বা থ্রেড স্টোরেজ সময়কাল সহ স্থানীয়দের ধ্বংসের আদেশ খাঁটি LIFO এর তুলনায় যথেষ্ট জটিল, বিভাগটি দেখুন 3..6.৩[basic.start.term]
বেন ভয়েগট

2
"প্রোগ্রাম সমাপ্তির সময়" বাক্যাংশটি কঠোরভাবে সঠিক নয়। উইন্ডোজ dlls এর স্ট্যাটিক্স সম্পর্কে কী যা গতিশীলভাবে লোড এবং আনলোড করা হয়? স্পষ্টতই সি ++ স্ট্যান্ডার্ড মোটেও অ্যাসেমব্লির সাথে ডিল করে না (এটি যদি ভাল হত তবে তা হবে), তবে এখানে স্ট্যান্ডার্ডটি কী বলেছে সে সম্পর্কে একটি ব্যাখ্যা ভাল হবে। যদি "প্রোগ্রাম টার্মিনেশন এ" শব্দটি অন্তর্ভুক্ত করা হয় তবে এটি প্রযুক্তিগতভাবে গতিশীলভাবে লোড হওয়া অ্যাসেমব্লিগুলি অ-অনুসরন করে সি +++ এর যে কোনও বাস্তবায়ন করে।
রজার স্যান্ডার্স

2
@ মট্টি আমি বিশ্বাস করি না যে স্ট্যান্ডার্ডটি স্পষ্টভাবে গতিশীল লাইব্রেরিগুলিকে অনুমতি দেয়, তবে এখনও অবধি আমি বিশ্বাস করি না যে স্ট্যান্ডার্ডের মধ্যে বিশেষভাবে এমন কিছু রয়েছে যা এর বাস্তবায়নের সাথে দ্বন্দ্বপূর্ণ ছিল। অবশ্যই, এখানে ভাষাটি কঠোরভাবে বললে বলা হয় না যে স্থির বস্তুগুলি অন্য উপায়ের মাধ্যমে আগে ধ্বংস করা যায় না, কেবল যে মূল থেকে ফিরে আসতে বা std :: প্রস্থানকে কল করার সময় তাদের অবশ্যই ধ্বংস করা উচিত। যদিও আমি মনে করি একটি দুর্দান্ত সূক্ষ্ম রেখা।
রজার স্যান্ডার্স

125

মোটি অর্ডার সম্পর্কে সঠিক, তবে বিবেচনা করার মতো আরও কিছু জিনিস রয়েছে:

সংস্থাগুলি স্থানীয় স্ট্যাটিক্স ইতিমধ্যে সূচনা করা হয়েছে কিনা তা নির্দেশ করতে সাধারণত একটি লুকানো পতাকা চলক ব্যবহার করে এবং এই পতাকাটি ফাংশনে প্রতিটি প্রবেশের সময় পরীক্ষা করা হয়। স্পষ্টতই এটি একটি ছোট পারফরম্যান্স হিট, তবে উদ্বেগের আরও বেশি বিষয় হ'ল এই পতাকাটি থ্রেড-সেফ হওয়ার গ্যারান্টিযুক্ত নয়।

উপরের মতো যদি আপনার স্থানীয় স্থিতিশীল থাকে এবং fooএকাধিক থ্রেড থেকে ডাকা হয়, আপনার কাছে জাতিগত অবস্থা হতে plonkপারে যা ভুলভাবে বা একাধিকবার আরম্ভ হতে পারে। এছাড়াও, plonkএক্ষেত্রে এটি যেটি নির্মাণ করেছে তার চেয়ে আলাদা থ্রেড দ্বারা ধ্বংস হতে পারে।

স্ট্যান্ডার্ড যা বলে তা সত্ত্বেও, আমি স্থানীয় স্ট্যাটিক ধ্বংসের প্রকৃত ক্রম সম্পর্কে খুব সতর্ক থাকব, কারণ সম্ভবত এটি অবিচ্ছিন্নভাবে কোনও স্থির ধ্বংস হওয়ার পরেও বৈধ হওয়ার উপর নির্ভর করতে পারে এবং এটি খুঁজে পাওয়া সত্যিই কঠিন is


68
সি ++ 0 এক্সের স্থিতি সূচনা থ্রেড নিরাপদ থাকা দরকার। সুতরাং সাবধান থাকুন তবে জিনিসগুলি আরও ভাল হবে।
deft_code

সামান্য নীতি দিয়ে ধ্বংসাত্মক আদেশের বিষয়গুলি এড়ানো যায়। স্ট্যাটিক / গ্লোবাল অবজেক্টস (সিলেটলেটস, ইত্যাদি) তাদের পদ্ধতিতে অন্যান্য স্ট্যাটিক অবজেক্টগুলিতে অ্যাক্সেস পাবে না। তারা কেবল নির্মাতাদের অ্যাক্সেস করতে হবে যেখানে পদ্ধতিতে পরবর্তী অ্যাক্সেসের জন্য কোনও রেফারেন্স / পয়েন্টার সংরক্ষণ করা যেতে পারে। এটি নিখুঁত নয় তবে 99 টির ক্ষেত্রে এটি ঠিক করা উচিত এবং এটির ক্ষেত্রে এটি 999 কেস স্পষ্টভাবে মৎসকন্যা এবং কোড পর্যালোচনাতে ধরা উচিত। এটি এখনও একটি নিখুঁত
স্থিরতা নয়

আমি কিছুটা নুবহু, তবে কেন এই নীতিটি ভাষাতে প্রয়োগ করা যায় না?
cjcurrie

9
সি ++ 11 যেহেতু এটি আর কোনও সমস্যা নয়। মট্টির উত্তর সে অনুযায়ী আপডেট করা হয়েছে।
নীলাঞ্জন বসু

10

বিদ্যমান ব্যাখ্যাগুলি in. Standard-তে পাওয়া স্ট্যান্ডার্ডের আসল বিধি ছাড়া সত্যই সম্পূর্ণ নয়:

স্ট্যাটিক স্টোরেজ সময়কাল বা থ্রেড স্টোরেজ সময়কাল সহ সমস্ত ব্লক-স্কোপ ভেরিয়েবলের জিরো-ইনিশিয়ালাইজেশন অন্য কোনও সূচনা হওয়ার আগে সঞ্চালিত হয়। স্থিতিশীল স্টোরেজ সময়কাল সহ একটি ব্লক-স্কোপ সত্তার ধারাবাহিক সূচনা, যদি প্রযোজ্য হয় তবে এর ব্লকটি প্রথমে প্রবেশের আগে সম্পাদন করা হয়। স্ট্যাটিক বা থ্রেড স্টোরেজ সময়কাল সহ অন্যান্য ব্লক-স্কোপ ভেরিয়েবলের প্রাথমিক সূচনা করার জন্য একটি বাস্তবায়নের অনুমতি দেওয়া হয় যে নামাঙ্কিত সুযোগে স্থির বা থ্রেড স্টোরেজ সময়কাল সহ কোনও চলককে স্থিতিশীলভাবে সূচনা করার জন্য কোনও বাস্তবায়নের অনুমতি দেওয়া হয়। অন্যথায় এ জাতীয় পরিবর্তনশীল প্রথমদিকে নিয়ন্ত্রণ তার ঘোষণার মধ্য দিয়ে যায়; যেমন একটি পরিবর্তনশীল এটি আরম্ভের সমাপ্তির পরে প্রাথমিক হিসাবে বিবেচিত হয়। যদি কোনও ব্যতিক্রম ছুঁড়ে সূচনাটি প্রস্থান করে, প্রারম্ভিককরণটি সম্পূর্ণ নয়, সুতরাং পরবর্তী সময় নিয়ন্ত্রণ ঘোষণায় প্রবেশ করার পরে এটি আবার চেষ্টা করা হবে। ভেরিয়েবলটি আরম্ভ করার সময় যদি নিয়ন্ত্রণ একসাথে ঘোষণায় প্রবেশ করে, একযোগে সম্পাদন শুরুকরণের সমাপ্তির জন্য অপেক্ষা করবে। পরিবর্তনটি আরম্ভ করার সময় যদি নিয়ন্ত্রণ পুনরাবৃত্তভাবে ঘোষণাকে পুনরায় প্রবেশ করে, আচরণটি নির্ধারিত।


8

FWIW, কোডগিয়ার সি ++ বিল্ডার মান অনুযায়ী প্রত্যাশিত ক্রমে ধ্বংস করবেন না।

C:\> sample.exe 1 2
Created in foo
Created in if
Destroyed in foo
Destroyed in if

... ধ্বংসের আদেশের উপর নির্ভর না করার আরেকটি কারণ!


57
একটি ভাল যুক্তি না। আমি বলব এটি এই সংকলকটি ব্যবহার না করার জন্য এটি আরও একটি যুক্তি।
মার্টিন ইয়র্ক

26
হুম। আপনি যদি কেবল তাত্ত্বিকভাবে পোর্টেবল কোডের পরিবর্তে বাস্তব-বিশ্বের পোর্টেবল কোড তৈরি করতে আগ্রহী হন তবে আমার মনে হয় যে ভাষার কোন ক্ষেত্রগুলি সমস্যা সৃষ্টি করতে পারে তা জানা দরকারী। আমি অবাক হব যদি সি ++ বিল্ডার এটি পরিচালনা না করার ক্ষেত্রে অনন্য ছিল।
রডি

17
আমি সম্মত হলাম, আমি এই বাক্যটিকে বাদ দিয়ে বলি যে "কোন সংকলকরা সমস্যা সৃষ্টি করে এবং কোন ভাষার ক্ষেত্রে তারা এটি করে" "-পি
স্টিভ জেসপ

0

স্ট্যাটিক ভেরিয়েবল একবার খেলার মধ্যে এসেছেন প্রোগ্রাম সঞ্চালনের শুরু এবং এটি প্রোগ্রাম সঞ্চালনের প্রান্ত পর্যন্ত পাওয়া যায়।

স্ট্যাটিক ভেরিয়েবলগুলি মেমোরির ডেটা বিভাগে তৈরি করা হয় ।


এটি ফাংশন স্কোপে ভেরিয়েবলগুলির জন্য সত্য নয়
অ্যাওয়ারিজ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.