'নতুন' এবং 'মুছুন' কি সি ++ এ অবমূল্যায়িত হচ্ছে?


68

আমি এমন একটি কুইজে হোঁচট খেয়েছি যার সাথে বিভিন্ন আকারের অ্যারে ঘোষণা জড়িত। আমার মনে যে প্রথম জিনিসটি এসেছিল তা হ'ল newকমান্ডটি দিয়ে আমাকে এই জাতীয় গতিশীল বরাদ্দ ব্যবহার করতে হবে :

while(T--) {
   int N;
   cin >> N;
   int *array = new int[N];
   // Do something with 'array'
   delete[] array;
}

তবে, আমি দেখেছি যে সমাধানগুলির মধ্যে একটিতে নিম্নলিখিত কেসটির অনুমতি দেওয়া হয়েছে:

while(T--) {
    int N;
    cin >> N;
    int array[N];
    // Do something with 'array'
}

কিছুটা গবেষণার পরে আমি পড়লাম যে জি ++ এটির অনুমতি দেয় তবে এটি আমাকে ভাবতে থাকে, কোন ক্ষেত্রে গতিশীল বরাদ্দ ব্যবহার করা দরকার? বা এটি যে সংকলকটি এটিকে গতিময় বরাদ্দ হিসাবে অনুবাদ করে?

মুছে ফাংশন অন্তর্ভুক্ত করা হয়। নোট, তবে, যে এখানে প্রশ্ন মেমরি ফাঁস সম্পর্কে নয়।


54
দ্বিতীয় উদাহরণটিতে একটি চলক-দৈর্ঘ্যের অ্যারে ব্যবহার করা হয় যা কখনও সি ++ এর অংশ হয় নি। এই ক্ষেত্রে std::vectorপরিবর্তে ( std::vector<int> array(N);) ব্যবহার করুন ।
কিছু প্রোগ্রামার ডিউড

7
আপনার প্রশ্নের সরাসরি উত্তরটি হওয়া উচিত: না, এটি হ্রাস পাচ্ছে না। যদিও সি ++ এর আধুনিক সংস্করণগুলি মেমরির মালিকানা পরিচালন (স্মার্ট পয়েন্টার) সরলকরণের জন্য অনেকগুলি বৈশিষ্ট্য সরবরাহ করে, তবুও new OBJসরাসরি অনুরোধ করে অবজেক্টগুলি বরাদ্দ করা এখনও সাধারণ অভ্যাস ।
pptaszni

8
লোকেরা মেমোরি ফাঁস সম্পর্কে কেন কথা বলছে তা নিয়ে বিভ্রান্ত হয়ে থাকা অন্যান্য ব্যক্তিদের জন্য, প্রশ্নটি এমন কোনও বাগটি সংশোধন করার জন্য সম্পাদিত হয়েছিল যা প্রশ্নের উপাদান ছিল না
মাইক কারন

4
@ মান্নোজ গতি এবং স্ট্যাকের জন্য ডায়নামিক এবং অটোমেটিক পদটি ব্যবহার করতে পছন্দ করেন। এটি বিরল তবে গাদা এবং স্ট্যাক ছাড়াই সি ++ প্রয়োগ করা সম্ভব।
ব্যবহারকারী 4581301

1
সি ++ তে কখনও কিছুই হ্রাস করা হয়নি এবং কখনও কিছুই হবে না। এটি সি ++ এর অর্থের একটি অংশ part
জোয়েলফ্যান

উত্তর:


114

আপনি যে স্নিপেট দেখান তা হ'ল মূর্তিযুক্ত, আধুনিক সি ++ কোড নয়।

newএবং delete(এবং new[]এবং delete[]) সি ++ এ অবমূল্যায়িত হয় না এবং কখনই হবে না। তারা এখনও গতিশীলভাবে বরাদ্দকৃত অবজেক্টগুলিকে ইনস্ট্যান্ট করার উপায়। যাইহোক, আপনার সর্বদা newএকটি delete(এবং একটি এর new[]সাথে delete[]) এর সাথে একটি মিল রাখতে হবে, সেগুলি (গ্রন্থাগার) শ্রেণীর মধ্যে সবচেয়ে ভাল রাখা হয় যা এটি আপনার পক্ষে নিশ্চিত করে। দেখুন সি ++ প্রোগ্রামারদের কেন 'নতুন' ব্যবহার কম করা উচিত?

আপনার প্রথম স্নিপেট একটি "নগ্ন" ব্যবহার করে new[]এবং তারপরে কখনই delete[]তৈরি করা অ্যারে ব্যবহার করে না। ঐটা একটা সমস্যা. std::vectorআপনার এখানে যা দরকার সবকিছু ঠিক আছে। এটি newপর্দার আড়ালে কিছু ফর্ম ব্যবহার করবে (আমি বাস্তবায়নের বিশদগুলিতে ডুব দেব না) তবে আপনাকে যে সমস্ত যত্ন নিতে হবে, এটি একটি গতিশীল অ্যারে তবে আরও ভাল এবং নিরাপদ।

আপনার দ্বিতীয় স্নিপেটটি "পরিবর্তনশীল দৈর্ঘ্যের অ্যারে" (ভিএলএএস) ব্যবহার করে, একটি সি বৈশিষ্ট্য যা কিছু সংকলক এছাড়াও সি ++ এ এক্সটেনশন হিসাবে মঞ্জুরি দেয়। বিপরীতে new, ভিএলএগুলি মূলত স্ট্যাকের উপর বরাদ্দ করা হয় (খুব সীমাবদ্ধ সংস্থান)। তবে আরও বড় কথা, এগুলি স্ট্যান্ডার্ড সি ++ বৈশিষ্ট্য নয় এবং এগুলি এড়ানো উচিত কারণ তারা পোর্টেবল নয়। তারা অবশ্যই গতিশীল (অর্থাত্ হিপ) বরাদ্দ প্রতিস্থাপন করে না।


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

4
এছাড়াও মনে রাখবেন যে আপনি কোনও অ্যারে ফিরিয়ে নিতে বা এটি অন্য কোথাও সঞ্চয় করতে পারবেন না, সুতরাং ভিএলএ কোনও দিন কার্য সম্পাদনের সময়কে ছাড়িয়ে যাবে না
রুস্লান

16
@ স্ট্যাকট্রেসার আমার জ্ঞানের সর্বোপরি, এমএসভিসি ভিএলএস সমর্থন করে না। এবং এমএসভিসি অবশ্যই একটি "প্রধান সংকলক"।
সর্বোচ্চ ল্যাঙ্গোফ

2
"আপনাকে সর্বদা একটি মুছার সাথে একটি নতুনের সাথে মিল রাখতে হবে" - আপনি যদি কাজ করেন না তবে Qtএর বেস ক্লাসগুলিতে সমস্ত আবর্জনা সংগ্রাহক রয়েছে, তাই আপনি কেবল ব্যবহার করেন newএবং বেশিরভাগ সময় ভুলে যান। জিইউআই উপাদানগুলির জন্য, প্যারেন্ট উইজেট বন্ধ হয়ে গেলে বাচ্চারা সুযোগের বাইরে চলে যায় এবং স্বয়ংক্রিয়ভাবে আবর্জনা সংগ্রহ করে।
বনাম

6
@vsz এমনকি কিউটিতে, প্রত্যেকটির newএখনও একটি মিল রয়েছে delete; এটি ঠিক যে deletes গুলি একই কোড ব্লকের পরিবর্তে প্যারেন্ট উইজেট দ্বারা সম্পন্ন হয় new
jjramsey

22

ঠিক আছে, সূচনাকারীদের জন্য, new/ অবচয় করা deleteহচ্ছে না।

আপনার নির্দিষ্ট ক্ষেত্রে, যদিও এগুলি একমাত্র সমাধান নয়। আপনি যা চয়ন করেন তা নির্ভর করে আপনার "অ্যারের সাথে কিছু করুন" মন্তব্যের আড়ালে কী লুকিয়ে আছে on

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

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

শুরুতে ফিরে চক্কর, vector হবে সম্ভবত ব্যবহার newকয়েক স্তর গভীর, কিন্তু আপনি যে সঙ্গে সংশ্লিষ্ট করা উচিত নয় হিসাবে ইন্টারফেস এটি উপস্থাপন অনেক শ্রেয়। সেই অর্থে ব্যবহার করা newএবং deleteনিরুৎসাহিত বলে বিবেচনা করা যেতে পারে।


1
"... কয়েকটি স্তর আরও গভীর" নোট করুন। আপনি যদি নিজের কন্টেনারগুলি প্রয়োগ করেন তবে আপনার এখনও ব্যবহার newএবং এড়ানো উচিত deleteনয়, বরং স্মার্ট পয়েন্টারগুলি পছন্দ করুন std::unique_pointer
সর্বোচ্চ

1
যা আসলে বলা হয়std::unique_ptr
user253751

2
@ ম্যাক্স: std::unique_ptrএর ডিফল্ট ডেস্ট্রাক্টর কল deleteবা delete[]যার অর্থ হ'ল মালিকানাধীন বস্তুটি অবশ্যই newবা এর মাধ্যমে বরাদ্দ করা উচিত new[], যা কলগুলি std::make_uniqueসি ++ 14 সাল থেকে লুকিয়ে রাখা হয়েছে।
লরেন্ট এলএ রিজ্জা

15

আপনার দ্বিতীয় উদাহরণ ব্যবহার পরিবর্তনশীল দৈর্ঘ্য অ্যারে (VLAs), যা আসলে একটি হয় C99 ( না সি ++!) বৈশিষ্ট্য, কিন্তু তা সত্ত্বেও দ্বারা সমর্থিত গ্রাম ++,

আরও দেখুন এই উত্তর

নোট করুন যে পরিবর্তনশীল দৈর্ঘ্যের অ্যারেগুলি new/ থেকে আলাদা deleteএবং এগুলি কোনওভাবেই " হ্রাস " করে না।

সতর্ক থাকতে হবে যে VLAs হয় হউন না আইএসও সি ++।


13

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

  int size=100;

  // This construct requires the matching delete statement.
  auto buffer_old = new int[size];

  // These versions do not require `delete`:
  std::unique_ptr<int[]> buffer_new (new int[size]);
  std::shared_ptr<int[]> buffer_new (new int[size]); 
  std::vector<int> buffer_new (size);  int* raw_access = buffer_new.data();

সি ++ 14 থেকে আপনিও লিখতে পারেন

auto buffer_new = std::make_unique<int[]>(size);

এটি আরও সুন্দর দেখায় এবং বরাদ্দ ব্যর্থ হলে মেমরি ফাঁস রোধ করবে। সি ++ থেকে আপনি যতটা করতে সক্ষম হবেন

auto a = std::make_shared<int[]>(size);

এটি আমার জন্য এখনও জিসিসি 7.4.0 দিয়ে লেখার সময় সংকলন করে না। এই দুটি উদাহরণে আমরা autoবামে প্রজ্ঞাপনের পরিবর্তে ব্যবহার করি । সব ক্ষেত্রে, যথারীতি অ্যারে ব্যবহার করুন:

buffer_old[0] = buffer_new[0] = 17;

newদ্বিগুণ থেকে মেমরি ফাঁস এবং ক্র্যাশ deleteহ'ল সি ++ এমন কিছু বিষয় যা বহু বছরের জন্য ভিত্তি করে রাখা হয়েছিল, অন্য ভাষাগুলিতে স্যুইচ করার পক্ষে যুক্তির "কেন্দ্রীয় পয়েন্ট"। এড়ানো আরও ভাল।


আপনার unique/shared_ptrপক্ষে কন্সট্রাক্টরদের এড়ানো উচিত make_unique/shared, কেবল আপনাকে দু'বার (ব্যবহার করে auto) নির্মিত টাইপটি লিখতে হবে না তবে নির্মাণ যদি পার্শ্ববর্তী স্থানে ব্যর্থ হয় তবে আপনি যদি মেমরি বা সংস্থানগুলি ফাঁস করার ঝুঁকি নেন না (যদি আপনি এমন কোনও ধরণের ব্যবহার করতে পারেন যা ব্যর্থ হতে পারে)
সাইমন বুচান

2
Make_unique সি ++ 14 এর অ্যারেগুলির সাথে উপলভ্য, এবং কেবল সি ++ 20 থেকে মেক_শ্যাটার করা আছে। এটি এখনও খুব কমই একটি ডিফল্ট সেটিংস তাই স্ট্যান্ড :: মেক_শ্রেড <int []> (আকার) সময়ের প্রস্তাব আগে আমার চেয়ে কিছুটা আগে চেয়েছিল।
অড্রিয়াস মেসকাউকাস

যথেষ্ট ফর্সা! make_shared<int[]>যখন আপনি প্রায় সবসময় চান তখন আমি সত্যিই খুব বেশি ব্যবহার করি না vector<int>, তবে তা জেনে রাখা ভাল।
সাইমন বুচান

অতিরিক্ত পেডেন্ট্রি, তবে আইআইআরসি unique_ptrকনস্ট্রাক্টর নোহ্রো, সুতরাং এর জন্য Tনোথ্রো কনস্ট্রাক্টর রয়েছে, সুতরাং এর সাথে ফাঁসের ঝুঁকি নেই unique_ptr(new int[size])এবং shared_ptrরয়েছে: "যদি কোনও ব্যতিক্রম ছুঁড়ে দেওয়া হয়, টি টি অ্যারের ধরণের না হলে মুছুন পিটি বলা হয়, মুছুন [ ] পি অন্যথায়। ", সুতরাং আপনার একই প্রভাব রয়েছে - ঝুঁকিটি হ'ল unique/shared_ptr(new MyPossiblyAllocatingType[size])
সাইমন বুচান

3

নতুন এবং মুছে ফেলা হয় না।

নতুন অপারেটর দ্বারা নির্মিত বস্তুগুলি রেফারেন্স দ্বারা পাস করা যেতে পারে। মুছে ফেলা ব্যবহার করে অবজেক্টগুলি মুছতে পারে।

নতুন এবং মুছুন ভাষাটির মূল বিষয়গুলি। নতুন এবং মুছে ফেলা ব্যবহার করে কোনও বস্তুর অধ্যবসায় পরিচালনা করা যায়। এগুলি অবশ্যই অবচয় করা হবে না।

বিবৃতি - int অ্যারে [এন] একটি অ্যারে সংজ্ঞায়নের একটি উপায়। অ্যারেটি এনকোলেসিং কোড ব্লকের ক্ষেত্রের মধ্যে ব্যবহার করা যেতে পারে। এটি কোনও বস্তুর অন্য ফাংশনে কীভাবে প্রেরণ করা হয় তার মতো পাস করা যায় না।


2

প্রথম উদাহরণটির delete[]শেষে একটি প্রয়োজন বা আপনার একটি স্মৃতি ফাঁস হবে।

দ্বিতীয় উদাহরণটি ভেরিয়েবল অ্যারে দৈর্ঘ্য ব্যবহার করুন যা সি ++ দ্বারা সমর্থিত নয়; এটি কেবল অ্যারে দৈর্ঘ্যের জন্য ধ্রুবক-প্রকাশের অনুমতি দেয়

এই ক্ষেত্রে এটি std::vector<>সমাধান হিসাবে ব্যবহার করা দরকারী ; এটি আপনাকে একটি টেম্পলেট শ্রেণিতে অ্যারেতে সম্পাদন করতে পারে এমন সমস্ত ক্রিয়া মোড়ানো।


3
"C ++ 11 অবধি" এর অর্থ কী? আমি বেশ নিশ্চিত, ভিএলএএস কখনও স্ট্যান্ডার্ডের অংশ হয় নি।
চুরিল

সি ++ ১৪ এর স্ট্যান্ডার্ড দেখুন [সি ++ 14 স্ট্যান্ডার্ড] ( আইসোক্প ..org / ফাইলস / পেপারস / এন 3690.pdf ) পৃষ্ঠায় 184 অনুচ্ছেদে 8.3.4
জিগ রেজার

4
এখানেই না । মান, কিন্তু শুধুমাত্র একটি খসড়া এবং "আবদ্ধ রানটাইম অ্যারে" এটা মান মধ্যে করেননি যতদূর আমি বলতে পারেন সম্পর্কে অংশ cppreference । VLAs সেখানে উল্লেখ নেই
churill

1
@ জিগরাজোর সিপ্পিফারেন্স.কমের প্রতিটি মান প্রকাশের আগে / পরে নিকটতম খসড়াগুলির লিঙ্কগুলির একটি তালিকা রয়েছে। প্রকাশিত মানগুলি অবাধে উপলভ্য নয় তবে এই খসড়াগুলি খুব কাছাকাছি হওয়া উচিত। আপনি নথির নম্বরগুলি থেকে দেখতে পাচ্ছেন, আপনার লিঙ্কযুক্ত খসড়াটি সি ++ 14 এর জন্য কিছু পুরানো কার্যকরী খসড়া।
আখরোট

2
@Learning_dude এটি মান দ্বারা সমর্থিত নয় । উত্তরটি (এখনই সংক্ষিপ্ত) সঠিক। এটি কেবল আপনার জন্য কাজ করে কারণ জিসিসি এটি একটি মানহীন এক্সটেনশন হিসাবে অনুমতি দেয় ।
আখরোট

-4

সিনট্যাক্সটি দেখতে সি ++ এর মতো, তবে আইডিয়ামটি পুরানো আলগোল 60 এর সমান। এটির মতো কোড ব্লক থাকা সাধারণ ছিল:

read n;
begin
    integer array x[1:n];
    ... 
end;

উদাহরণটি লিখিত হতে পারে:

while(T--) {
    int N;
    cin >> N;
    {
        int array[N];
        // Do something with 'array'
    }
}

আমি মাঝে মাঝে এটি বর্তমান ভাষাগুলিতে মিস করি;)

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