কোন ক্ষেত্রে আমি ম্যালোক এবং / অথবা নতুন ব্যবহার করব?


479

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

আপনি যদি একজন সি ++ বিশেষজ্ঞ হন তবে দয়া করে আমাকে এই বিষয়ে অনুসরণকারী থাম্ব বা কনভেনশনগুলির কোনও নিয়ম জানান।


33
আমি কেবল একটি অনুস্মারক যুক্ত করতে চাই যে আপনি দুটি শৈলীর মিশ্রণ করতে পারবেন না - এটি হ'ল আপনি কোনও অবজেক্ট তৈরি করতে নতুন ব্যবহার করতে পারবেন না এবং তারপরে ফ্রি () কল করতে পারবেন না বা ম্যালোক () দ্বারা বরাদ্দকৃত কোনও ব্লক মুছতে চেষ্টা করবেন না। সম্ভবত এটি বলা সুস্পষ্ট, তবে তবুও ...
nsayer

32
ভাল উত্তর, আমাকে যুক্ত করতে হবে (যা আমি দেখিনি) হ'ল নতুন / মুছে ফেলা আপনার জন্য কনস্ট্রাক্টর / ডেস্ট্রাক্টরকে কল করে, ম্যালোক / ফ্রি করে না। উল্লেখযোগ্য মাত্র একটি পার্থক্য।
বিল কে

আধুনিক সি ++ সহ, আমি এখনও ব্যবহার করার কারণ খুঁজে পাওয়ার চেষ্টা করছি।
রাহলি

অথবা উভয়ই ব্যবহার করুন এবং স্ট্যান্ডার্ড: শেয়ারড_প্টার <টি> এর সাথে যান। তাহলে আপনাকে একেবারেই মুছতে হবে না।
ভিনসেন্ট

উত্তর:


387

আপনাকে সি ব্যবহার করতে বাধ্য করা না হলে আপনার কখনই ব্যবহার করা উচিত নয়malloc । সর্বদা ব্যবহার new

আপনার যদি খুব বড় ডেটা দরকার হয় তবে কিছু করুন:

char *pBuffer = new char[1024];

এটি সঠিক না হলেও সতর্ক থাকুন:

//This is incorrect - may delete only one element, may corrupt the heap, or worse...
delete pBuffer;

পরিবর্তে আপনার ডেটা অ্যারে মুছে ফেলার সময় এটি করা উচিত:

//This deletes all items in the array
delete[] pBuffer;

newশব্দ এরকম সি ++ উপায়, এবং এটা নিশ্চিত করবে যে আপনার টাইপ তার হবে কন্সট্রাকটর নামকnewশব্দ এছাড়াও আরো টাইপ-নিরাপদ যেহেতু mallocটাইপ-নিরাপদ নয় এ সব।

আমি ভাবতে পারি যে এটি ব্যবহার করা উপকারী mallocহবে কেবল যদি আপনার আপনার বাফার ডেটার আকার পরিবর্তন করার প্রয়োজন হয় । newশব্দ মতো অনুরূপ ভাবে নেই reallocreallocফাংশন আরো দক্ষতার সঙ্গে তোমার জন্য মেমরি একটি খণ্ড আকার প্রসারিত করতে সক্ষম হতে পারেন।

এটি উল্লেখযোগ্য যে আপনি new/ freeএবং malloc/ মিক্স করতে পারবেন না delete

দ্রষ্টব্য: এই প্রশ্নের কয়েকটি উত্তর অবৈধ।

int* p_scalar = new int(5);  // Does not create 5 elements, but initializes to 5
int* p_array  = new int[5];  // Creates 5 elements

2
আপনি যখন মুছুন [] foo কল করতে চান কল করার বিষয়ে, কিছু সংকলক আপনার জন্য এটি স্বয়ংক্রিয়ভাবে সমাধান করবে এবং ফাঁস হবে না এবং অন্যান্য কেবল প্রথম প্রবেশ এবং ফাঁস মুছবে। আমার কিছু কোডে এর কয়েকটি ছিল এবং ভ্যালগ্রাইন্ড সেগুলি আপনার জন্য খুঁজে পাবে।
কেপেক্সএএ

30
আপনি যদি সঠিক ডিলিটটি ব্যবহার না করেন তবে ফলাফলটি সংজ্ঞায়িত । এটা ভুল কখনও কখনও এটি জিনিসটির সঠিক অংশ বা কাজ পেতে পারে তা হ'ল অন্ধ ভাগ্য।
মাইকেল বুড়

8
@ কেপেক্সিয়া: এমনকি যদি কিছু সংকলক আপনার ভুলগুলিও ঠিক করতে পারে তবে এগুলি প্রথম স্থানে তৈরি করা এখনও ভুল wrong :) যথাযথ যেখানে প্রয়োজন সেখানে সর্বদা মুছুন use
করোনায়

62
"যদি আপনি সি ব্যবহার করতে বাধ্য না হন তবে আপনার কখনও ম্যালোক ব্যবহার করা উচিত নয় Always সর্বদা নতুন ব্যবহার করুন।" কেন? এখানে জয় কি? অবজেক্টের জন্য আমাদের নির্মাণ প্রয়োজন, তবে মেমোরি ব্লকগুলির জন্য, আপনি কোডিং ভুলগুলি করার জন্য দুটি উপায় স্পষ্ট করে নথিবদ্ধ করেছেন (আরও সহজে ধরা পড়ে () বনাম [] নতুনতে এবং সহজেই কম ধরা পড়েছে মেলানো অ্যারে বনাম স্কেলার নতুন এবং মুছুন)। কাঁচা মেমরির ব্লকগুলির জন্য নতুন / মুছা ব্যবহারের অনুপ্রেরণা কী?
বেন সুপনিক

3
@ ডেড এমএমজি: যদি কেউ একটি অ্যাসিনক্রোনাস এপিআই ফাংশন ব্যবহারের জন্য একটি অ্যারে তৈরি করে থাকে তবে এর new[]চেয়ে বেশি নিরাপদ হবে না std::vector? যদি একটি ব্যবহার করে new[]তবে পয়েন্টারটি অবৈধ হয়ে যাওয়ার একমাত্র উপায় স্পষ্টর মাধ্যমে হবে delete, অন্যদিকে std::vectorযখন ভেক্টরকে পুনরায় আকার দেওয়া হয় বা সুযোগ ছেড়ে যায় তখন কোনওটির জন্য বরাদ্দকৃত মেমরিটি অবৈধ হতে পারে । (নোট করুন যে কোনওটি ব্যবহার করার সময় অ্যাসিঙ্ক পদ্ধতিটি বিচারাধীন থাকলেও new[]কল করতে সক্ষম না হওয়ার সম্ভাবনাটি মঞ্জুর deleteকরতে হবে; যদি এসিএনসি অপারেশনটি ত্যাগ করার প্রয়োজন হতে পারে তবে একজনকে কলব্যাকের মাধ্যমে মুছে ফেলার ব্যবস্থা করতে হবে) ।
সুপারক্যাট

144

সংক্ষিপ্ত উত্তরটি হ'ল mallocসি ++ এর জন্য এটি করার জন্য কোনও ভাল কারণ ছাড়াই ব্যবহার করবেন না । mallocসি ++ এর সাথে ব্যবহার করার সময় বেশ কয়েকটি ঘাটতি রয়েছে যা newঅতিক্রম করতে সংজ্ঞায়িত হয়েছিল।

সি ++ কোডের জন্য নতুন দ্বারা ঘাটতিগুলি ঠিক করা হয়েছে

  1. mallocকোনও অর্থবহ উপায়ে টাইপসেফ নয়। সি ++ এ আপনাকে রিটার্নটি কাস্ট করতে হবে void*। এটি সম্ভাব্য অনেক সমস্যার পরিচয় দেয়:

    #include <stdlib.h>
    
    struct foo {
      double d[5];
    }; 
    
    int main() {
      foo *f1 = malloc(1); // error, no cast
      foo *f2 = static_cast<foo*>(malloc(sizeof(foo)));
      foo *f3 = static_cast<foo*>(malloc(1)); // No error, bad
    }
    
  2. যদিও এটি তার চেয়েও খারাপ। যদি প্রশ্নের ধরণটি হ'ল পিওডি (সাধারণ পুরাতন ডেটা) হয় তবে আপনি mallocএটির জন্য মেমরি বরাদ্দ করতে আধা-সংবেদনশীলভাবে ব্যবহার করতে পারেন , যেমন f2প্রথম উদাহরণে।

    কোনও প্রকারের পিওডি হলেও এটি এতটা স্পষ্ট নয়। কোনও প্রদত্ত প্রকারের জন্য কোনও ফলাফলের সংকলক ত্রুটি না করে এবং সম্ভাব্যভাবে ডিবাগ করা সমস্যাগুলির পক্ষে খুব শক্তভাবে কোনও POD থেকে নন-পিওডে পরিবর্তন করা সম্ভব তা একটি গুরুত্বপূর্ণ কারণ factor উদাহরণস্বরূপ, যদি কেউ (সম্ভবত অন্য কোনও প্রোগ্রামার, রক্ষণাবেক্ষণের সময়, পরে অনেক পরে এমন একটি পরিবর্তন করতে থাকে যা fooআর পিওডি না হয়ে থাকে তবে আপনার আশা মতো সংকলনের সময় কোনও সুস্পষ্ট ত্রুটি উপস্থিত হবে না, যেমন:

    struct foo {
      double d[5];
      virtual ~foo() { }
    };
    

    করতে হবে mallocএর f2আরো পরিণত খারাপ, কোন সুস্পষ্ট ডায়গনিস্টিক ছাড়া। এখানে উদাহরণটি তুচ্ছ, তবে দুর্ঘটনাক্রমে আরও অনেক দূরে নন-পডনেস পরিচয় করানো সম্ভব (যেমন একটি বেস ক্লাসে, কোনও নন-পিওডি সদস্য যুক্ত করে)। আপনার যদি সি ++ 11 / বুস্ট থাকে তবে আপনি is_podএই অনুমানটি সঠিক কিনা তা পরীক্ষা করে ব্যবহার করতে পারেন এবং যদি তা না হয় তবে একটি ত্রুটি তৈরি করতে পারেন:

    #include <type_traits>
    #include <stdlib.h>
    
    foo *safe_foo_malloc() {
      static_assert(std::is_pod<foo>::value, "foo must be POD");
      return static_cast<foo*>(malloc(sizeof(foo)));
    }
    

    যদিও বুস্ট সি ++ 11 বা অন্য কোনও সংকলক এক্সটেনশান ছাড়াই কোনও ধরণের পিওডি কিনা তা নির্ধারণ করতে অক্ষম

  3. mallocNULLবরাদ্দ ব্যর্থ হলে ফেরত দেয় । newনিক্ষেপ করা হবে std::bad_alloc। পরে NULLপয়েন্টার ব্যবহারের আচরণ অপরিজ্ঞাত। একটি ব্যতিক্রম পরিষ্কার তদন্তে থাকে যখন এটি নিক্ষেপ করা হয় এবং এটি ত্রুটির উত্স থেকে ফেলে দেওয়া হয়। mallocপ্রতিটি কলে যথাযথ পরীক্ষার সাথে জড়ো করা ক্লান্তিকর এবং ত্রুটির প্রবণ বলে মনে হয়। (সমস্ত ভাল কাজ পূর্বাবস্থায় ফেলার জন্য আপনাকে একবারে ভুলে যেতে হবে)। একজন ব্যতিক্রমকে এমন একটি স্তরে ছড়িয়ে পড়ার অনুমতি দেওয়া যেতে পারে যেখানে একজন কলার সংবেদনশীলতার সাথে এটি প্রক্রিয়া করতে সক্ষম হন, যেখানে NULLঅর্থপূর্ণভাবে ফিরে যাওয়া আরও শক্ত। আমরা safe_foo_mallocএকটি ব্যতিক্রম ছুঁড়তে বা প্রোগ্রামটি থেকে বেরিয়ে আসতে বা কোনও হ্যান্ডলারকে কল করতে আমাদের ফাংশনটি বাড়িয়ে দিতে পারি :

    #include <type_traits>
    #include <stdlib.h>
    
    void my_malloc_failed_handler();
    
    foo *safe_foo_malloc() {
      static_assert(std::is_pod<foo>::value, "foo must be POD");
      foo *mem = static_cast<foo*>(malloc(sizeof(foo)));
      if (!mem) {
         my_malloc_failed_handler();
         // or throw ...
      }
      return mem;
    }
    
  4. মূলত mallocএকটি সি বৈশিষ্ট্য এবং newএটি একটি সি ++ বৈশিষ্ট্য। ফলস্বরূপ mallocকন্সট্রাক্টরদের সাথে সুন্দরভাবে খেলা হয় না, এটি কেবলমাত্র বাইটের একটি অংশ বরাদ্দ করার দিকে নজর দেয়। safe_foo_mallocপ্লেসমেন্ট ব্যবহারের জন্য আমরা আমাদের আরও বাড়িয়ে দিতে পারি new:

    #include <stdlib.h>
    #include <new>
    
    void my_malloc_failed_handler();
    
    foo *safe_foo_malloc() {
      void *mem = malloc(sizeof(foo));
      if (!mem) {
         my_malloc_failed_handler();
         // or throw ...
      }
      return new (mem)foo();
    }
    
  5. আমাদের safe_foo_mallocফাংশনটি খুব জেনেরিক নয় - আদর্শভাবে আমরা এমন কিছু চাই যা কেবলমাত্র নয়, যে কোনও ধরণের পরিচালনা করতে পারে foo। আমরা অ-ডিফল্ট নির্মাতাদের জন্য টেমপ্লেট এবং বৈকল্পিক টেম্পলেটগুলির সাথে এটি অর্জন করতে পারি:

    #include <functional>
    #include <new>
    #include <stdlib.h>
    
    void my_malloc_failed_handler();
    
    template <typename T>
    struct alloc {
      template <typename ...Args>
      static T *safe_malloc(Args&&... args) {
        void *mem = malloc(sizeof(T));
        if (!mem) {
           my_malloc_failed_handler();
           // or throw ...
        }
        return new (mem)T(std::forward(args)...);
      }
    };
    

    এখন পর্যন্ত আমরা এখন পর্যন্ত চিহ্নিত সমস্ত সমস্যার সমাধানের ক্ষেত্রে আমরা কার্যত ডিফল্ট newঅপারেটরটিকে নতুনভাবে তৈরি করেছি । আপনি যদি ব্যবহার mallocএবং অবস্থান নির্ধারণ করতে যাচ্ছেন newতবে আপনি পাশাপাশি newশুরু করতে ব্যবহার করতে পারেন !


27
এটি খুব খারাপ সি ++ তৈরি structএবং classমূলত একই জিনিসটির অর্থ; আমি ভাবছি যদি structPODs এর জন্য সংরক্ষিত থাকায় এবং সম্ভবত সমস্ত classপ্রকারটি নন-পিওডি বলে মনে করা হত যে কোনও সমস্যা হত। কোড দ্বারা সংজ্ঞায়িত যে কোনও ধরণের যা সি +++ এর আবিষ্কারের পূর্বাভাস করেছিল তা অগত্যা পিওডি হবে, সুতরাং আমি মনে করি না যে পশ্চাদপদ সামঞ্জস্যতা সেখানে সমস্যা হয়ে উঠবে। নন-পিওডি প্রকারের structপরিবর্তে ঘোষিত হওয়ার কি সুবিধা রয়েছে class?
সুপারক্যাট

1
@ সুপের্যাট কিছুটা দেরী হয়েছে তবে দেখা যাচ্ছে যে প্রায় একই জিনিস তৈরি করা structএবং classকরা একটি দুর্দান্ত ডিজাইনের সিদ্ধান্ত ছিল যা এখন "মেটাচ্লাস" (হার্ব থেকে) নামে একটি ঝরঝরে বৈশিষ্ট্য সক্ষম করে ।
Rakete1111

@ রেকেট 1111: প্রথম নজরে, প্রস্তাবটি দেখে মনে হচ্ছে এটি ডলার-প্রিফিক্স কীওয়ার্ড ব্যবহার করে এমন ভাষার কোনও সংস্করণকে প্রাক-প্রসেস করে $class। তবে আমি নিশ্চিত নই যে এর সাথে কী করতে হবে classএবং structপ্রতিশব্দ হচ্ছে।
সুপারক্যাট

@ সুপের্যাট টাইপ সিস্টেমটি আরও দ্বিখণ্ডিত হত। কার্যকরভাবে একই জিনিসটি বোঝানো classএবং structবোঝানোর দ্বারা , আপনি একটি এবং তদ্বিপরীত $classতৈরি করার চিন্তা না করে আপনি তাদের ( ) এ স্বেচ্ছাসেবী রূপান্তর করতে পারেন । classstruct
Rakete1111

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

53

থেকে সি ++ FQA লাইট :

[16.4] বিশ্বস্ত পুরাতন ম্যালোক () এর পরিবর্তে আমি কেন নতুন ব্যবহার করব?

এফএকিউ: নতুন / মুছে ফেলুন কনস্ট্রাক্টর / ডেস্ট্রাক্টর কল; নতুন টাইপ নিরাপদ, malloc নয়; নতুন কোনও শ্রেণীর দ্বারা ওভাররাইড করা যায়।

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

ওহ, এবং বিশ্বাসযোগ্য পুরানো ম্যালোক ব্যবহার সমানভাবে বিশ্বাসযোগ্য এবং পুরানো রিলোক ব্যবহার করা সম্ভব করে। খুব খারাপ যে আমাদের কাছে চকচকে নতুন অপারেটর নবায়ন বা কিছু নেই।

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

দুঃখিত, আমি কেবল প্রতিরোধ করতে পারিনি। :)


7

8
আমি এই মন্তব্যটিকে গুরুত্ব সহকারে নিতে পারি না কারণ এটি স্পষ্টতই সি ++ এর বিরুদ্ধে লেখকের পক্ষপাতিত্ব করে। সি ++ হ'ল এমন একটি ভাষা যা পারফরম্যান্স ভিত্তিক সফ্টওয়্যার তৈরি করতে ব্যবহৃত হয় এবং একটি আবর্জনা সংগ্রহকারী কেবল তার উদ্দেশ্যটির জন্য ক্ষতিকারক হতে পারে। আমি আপনার পুরো উত্তর সাথে একমত না!
মিগুয়েল

1
@ মিগুয়েল আপনি রসিকতা মিস করেছেন
ড্যান বেচার্ড

50

সি ++ এ সর্বদা নতুন ব্যবহার করুন। আপনার যদি টাইপযুক্ত মেমরির একটি ব্লক দরকার হয় তবে আপনি সরাসরি অপারেটরটি ব্যবহার করতে পারেন:

void *p = operator new(size);
   ...
operator delete(p);

3
আকর্ষণীয়, আমি যখনই এর মতো কোনও কাঁচা ডেটা বাফার প্রয়োজন তখন আমি সর্বদা স্বাক্ষরবিহীন চরের একটি অ্যারে বরাদ্দ করি।
গ্রেগ রজার্স

যত্নশীল সেমন্তিকগুলি এর মতো হওয়া উচিত: p_var = নতুন টাইপ (আরম্ভকারী); আকার নয়।
ব্রায়ান আর বন্ডি

11
আপনি যদি সরাসরি অপারেটরটিকে নতুন কল করেন না, তবে প্যারামিটার হিসাবে বরাদ্দ করতে বাইটসের সংখ্যা লাগে।
ফেরুকসিও

1
এইচআরএম নিশ্চিত নয়, আমি এই সিনট্যাক্সটির কথা কখনও শুনিনি।
ব্রায়ান আর বন্ডি

9
বিপরীত operator newহয় operator deletedeleteপ্রকারের সাথে কোনও এক্সপ্রেশনকে কল করা এটি কোনও সংজ্ঞায়িত ক্রিয়া নয় void*
সিবি বেইলি

33

শুধুমাত্র সি-কেন্দ্রিক লাইব্রেরি এবং এপিআই দ্বারা পরিচালিত হতে চলেছে এমন মেমরি বরাদ্দ করার জন্য mallocএবং ব্যবহার করুন । ব্যবহারের এবং (এবং রূপগুলো) সবকিছু যে আপনি নিয়ন্ত্রণ জন্য।free newdelete[]


10
এছাড়াও লক্ষ করুন যে ভাল লিখিত সি লাইব্রেরি অভ্যন্তরীণভাবে malloc এবং বিনামূল্যে লুকিয়ে রাখবে, সি প্রোগ্রামারকে এভাবে কাজ করা উচিত।
ডাকাভ

@ ডিএমকেকে আপনার কাছে সি -++ উদাহরণ রয়েছে যে ম্যালোক এবং বিনামূল্যে সি-কেন্দ্রিক লাইব্রেরি ব্যবহার করছেন?
মাইলমা

1
@ ডাকাভ: যদি কোনও সি ফাংশন কোনও জিনিসের জন্য একটি পয়েন্টার গ্রহণ করে যে ফাংশনটি ফিরে আসার পরে এটি ব্যবহার করা দরকার এবং কলারের কাছে জানার কোনও উপায় থাকবে না যে কখন বস্তুর প্রয়োজন রয়েছে, এটি ফাংশনটির জন্য পুরোপুরি যুক্তিসঙ্গত হবে নির্দিষ্ট করতে যে পয়েন্টারটি অবশ্যই তৈরি করা হয়েছিল malloc। তেমনিভাবে যদি কোনও ফাংশন যেমন strdupকোনও অবজেক্ট তৈরি করতে এবং তাকে একজন কলারের কাছে ফিরিয়ে দেওয়ার প্রয়োজন হয়, তবে কলারের কাছে freeআর প্রয়োজন নেই যখন অবজেক্টটিতে কল করতে হবে তা নির্দিষ্টভাবে যুক্তিসঙ্গত । এই জাতীয় ফাংশন কীভাবে কলকারীদের কাছে তাদের ম্যালোক / ফ্রি ব্যবহার প্রকাশ করা এড়াতে পারে?
সুপারক্যাট

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

@ সুপের্যাট প্রতিদিনের প্যাকেজের একটি উদাহরণ যা আমি নিশ্চিত যে সবাই ব্যবহার করেছে লিবিজিএমপি। আপনি যদি কখনও এ জাতীয় এনক্রিপশনের উপর ভিত্তি করে কোনও ওপেন-সোর্স এনক্রিপশন বা সফ্টওয়্যার ব্যবহার করেন (যা খুব সম্ভবত) তবে আপনি সম্ভবত একটি স্বেচ্ছাচারিত নির্ভুলতা পাটিগণিত গ্রন্থাগার ব্যবহার করেছেন যা তার নিজস্ব অভ্যন্তরীণ ডেটা বৃদ্ধি এবং সঙ্কুচিত করা প্রয়োজন। এটি একটি ইনিশিয়ালেশন ফাংশনটি ব্যবহার করে করা হয়েছে ... এবং তারপরে আপনি আশ্চর্য হবেন যে আপনি সি ++ তে সি কোডটি কীভাবে লিবগ্যাম্প হয় তা সি ++ এ পুনরায় সংবিধান না করে ব্যবহার করবেন? এখন মনে যে (linker) সঙ্গে, ... কেন কোন বুদ্ধিমান ব্যক্তি হবে এটা আমার মনে হয় কি করা mallocC ++?
অটিস্টিক

31

নতুন বনাম malloc ()

1) newএকটি অপারেটর , যখন malloc()একটি ফাংশন

2) কনস্ট্রাক্টরকেnew কল করে , যদিও না।malloc()

3) newফেরৎ সঠিক ডাটা টাইপ , যখন malloc()আয় অকার্যকর *

৪) newকখনই কোনও NUL ফেরত দেয় না (ব্যর্থতা ছুঁড়ে দেয়) যখন malloc()NULL দেয়

5) মেমরি পদ্ধতিতে পুনরায় বরাদ্দকরণের দ্বারা পরিচালিত না newযখন malloc()করতে পারেন


6
হাই, পয়েন্ট 4 এর জন্য) নতুনকে ব্যর্থতার পরে NULL ফেরত দেওয়ার জন্য নির্দেশ দেওয়া যেতে পারে। char* ptr = new (std::nothrow) char [323232];
সিং

1
6) কনস্ট্রাক্টর আর্গুমেন্ট থেকে নতুন তৈরি হয়, যখন ম্যালোক আকার ব্যবহার করে।
ইভান মুরান

এছাড়াও একটি newফাংশন রয়েছে
মা মিং

আপনি যদি পুনর্বিবেশন হিসাবে সি তে এত ঝুঁকছিলেন তবে আমি আশা করব যে আপনি তার reallocচেয়ে বেশি ব্যবহার করবেন mallocএবং আপনার পয়েন্টার ভেরিয়েবলটি আরম্ভ করে শুরু করবেন NULL। আপনি যদি অন্যদিকে, সি ++ তে একটি আকার পরিবর্তনযোগ্য মেমরি চান তবে আমি তার std::vectorবিপরীতে প্রস্তাব দিচ্ছি realloc... এটি বা কোনও ফাইল।
অটিস্টিক

19

আপনার প্রশ্নের উত্তর দেওয়ার জন্য, আপনার মধ্যে mallocএবং এর মধ্যে পার্থক্যটিnew জানা উচিত । পার্থক্যটি সহজ:

malloc মেমরি বরাদ্দ করে , যখন new মেমরি বরাদ্দ করে এবং যে মেমরিটির জন্য আপনি মেমরি বরাদ্দ করেন তার নির্মাতাকে কল করে

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

এছাড়াও মধ্যে পার্থক্য freeএবং deleteবেশ একই। পার্থক্যটি হ'ল deleteমেমরি মুক্ত করার পাশাপাশি আপনার অবজেক্টের ডেস্ট্রাক্টরকে কল করবে।


13

তার মাঝে এক বড় পার্থক্য mallocএবং newmallocস্মৃতি বরাদ্দ। এটি সি এর জন্য সূক্ষ্ম, কারণ সি-তে, মেমরির একগুচ্ছ বস্তু।

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

newমেমরি বরাদ্দ করে এবং সেই মেমরির অবস্থানটিতে একটি অবজেক্ট তৈরি করে। নন-পিওডি প্রকারের জন্য এর অর্থ কনস্ট্রাক্টরকে কল করা।

আপনি যদি এরকম কিছু করেন:

non_pod_type* p = (non_pod_type*) malloc(sizeof *p);

আপনি যে পয়েন্টারটি পান সেটি ডিফারেন্স করা যায় না কারণ এটি কোনও বস্তুর দিকে নির্দেশ করে না। আপনি এটির ব্যবহারের আগে আপনাকে এটিতে কোনও কনস্ট্রাক্টরের কল করতে হবে (এবং এটি স্থাপনার সাহায্যে সম্পন্ন করা হয়েছে new)।

অন্যদিকে, আপনি যদি:

non_pod_type* p = new non_pod_type();

আপনি একটি পয়েন্টার পান যা সর্বদা বৈধ, কারণ newএকটি বস্তু তৈরি করেছে।

এমনকি পিওডির ধরণের ক্ষেত্রেও দুটির মধ্যে একটি উল্লেখযোগ্য পার্থক্য রয়েছে:

pod_type* p = (pod_type*) malloc(sizeof *p);
std::cout << p->foo;

এই কোডের টুকরোটি একটি অনির্ধারিত মান প্রিন্ট করবে, কারণ তৈরি পিওডি অবজেক্টগুলি mallocআরম্ভ করা হয়নি।

এর সাথে new, আপনি কল করতে কোনও কনস্ট্রাক্টর নির্দিষ্ট করতে পারেন এবং এভাবে একটি ভাল সংজ্ঞাযুক্ত মান পেতে পারেন।

pod_type* p = new pod_type();
std::cout << p->foo; // prints 0

আপনি যদি সত্যিই এটি চান তবে আপনি newঅবিচ্ছিন্ন POD অবজেক্টগুলি ব্যবহার করতে ব্যবহার করতে পারেন । সে সম্পর্কে আরও তথ্যের জন্য এই অন্যান্য উত্তরটি দেখুন ।

আর একটি পার্থক্য হ'ল ব্যর্থতার উপর আচরণ। যখন এটি মেমরি বরাদ্দ করতে ব্যর্থ হয়, mallocএকটি নাল পয়েন্টার দেয়, যখন newএকটি ব্যতিক্রম ছুঁড়ে দেয়।

প্রাক্তনটির প্রত্যেকটি পয়েন্টার ব্যবহারের আগে ফিরে আসা আপনাকে পরীক্ষা করা প্রয়োজন, যখন পরে সর্বদা বৈধ পয়েন্টার উত্পাদন করে।

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

std::unique_ptr<T> p = std::unique_ptr<T>(new T()); // this won't leak

7

গতিশীল বরাদ্দ কেবল তখনই প্রয়োজন যখন অবজেক্টের আয়ু-সময়টি তৈরি হওয়ার সুযোগের চেয়ে আলাদা হওয়া উচিত (এটি ক্ষেত্রকে আরও বৃহত্তর করে তোলার জন্য এটি ধারণ করে) এবং আপনার কাছে একটি নির্দিষ্ট কারণ আছে যেখানে এটি মান দ্বারা সঞ্চয় করে না হবে।

উদাহরণ স্বরূপ:

 std::vector<int> *createVector(); // Bad
 std::vector<int> createVector();  // Good

 auto v = new std::vector<int>(); // Bad
 auto result = calculate(/*optional output = */ v);
 auto v = std::vector<int>(); // Good
 auto result = calculate(/*optional output = */ &v);

সি ++ 11 থেকে, আমাদের std::unique_ptrবরাদ্দ মেমরির সাথে কাজ করার জন্য রয়েছে, যা বরাদ্দ মেমরির মালিকানা ধারণ করে। std::shared_ptrযখন আপনাকে মালিকানা ভাগ করতে হবে তখনই তৈরি হয়েছিল। (একটি ভাল প্রোগ্রামে আপনি যেটা আশা করবেন তার চেয়ে কম আপনার প্রয়োজন হবে)

একটি উদাহরণ তৈরি করা সত্যিই সহজ হয়ে যায়:

auto instance = std::make_unique<Class>(/*args*/); // C++14
auto instance = std::make_unique<Class>(new Class(/*args*/)); // C++11
auto instance = std::make_unique<Class[]>(42); // C++14
auto instance = std::make_unique<Class[]>(new Class[](42)); // C++11

সি ++ 17 এছাড়াও যুক্ত করে std::optionalযা আপনাকে মেমরির বরাদ্দের প্রয়োজনীয়তা থেকে বাধা দিতে পারে

auto optInstance = std::optional<Class>{};
if (condition)
    optInstance = Class{};

'উদাহরণ' সুযোগের বাইরে যাওয়ার সাথে সাথে স্মৃতিশক্তি পরিষ্কার হয়ে যায়। মালিকানা স্থানান্তর করাও সহজ:

 auto vector = std::vector<std::unique_ptr<Interface>>{};
 auto instance = std::make_unique<Class>();
 vector.push_back(std::move(instance)); // std::move -> transfer (most of the time)

তাহলে আপনার এখনও কখন দরকার new? প্রায় কখনও সি ++ 11 থেকে নেই। আপনি বেশিরভাগই std::make_uniqueএমন কোনও বিন্দুতে না পৌঁছা পর্যন্ত ব্যবহার করেন যেখানে আপনি কাঁচা পয়েন্টারগুলির মাধ্যমে মালিকানা স্থানান্তর করে এমন একটি এআইপি মারেন।

 auto instance = std::make_unique<Class>();
 legacyFunction(instance.release()); // Ownership being transferred

 auto instance = std::unique_ptr<Class>{legacyFunction()}; // Ownership being captured in unique_ptr

সি ++ 98/03 এ আপনাকে ম্যানুয়াল মেমরি পরিচালনা করতে হবে। আপনি যদি এই ক্ষেত্রে থাকেন তবে মানকটির আরও সাম্প্রতিক সংস্করণে আপগ্রেড করার চেষ্টা করুন। যদি আপনি আটকে থাকেন:

 auto instance = new Class(); // Allocate memory
 delete instance;             // Deallocate
 auto instances = new Class[42](); // Allocate memory
 delete[] instances;               // Deallocate

কোনও মেমরি ফাঁস না হওয়ার জন্য আপনি মালিকানাটি সঠিকভাবে ট্র্যাক করেছেন তা নিশ্চিত করুন! সরানো শব্দার্থবিজ্ঞানগুলি এখনও কাজ করে না।

সুতরাং, যখন আমাদের সি ++ এ ম্যালোক প্রয়োজন? একমাত্র বৈধ কারণ হ'ল মেমরি বরাদ্দ করা এবং পরে নতুন স্থাপনার মাধ্যমে এটিকে আরম্ভ করা।

 auto instanceBlob = std::malloc(sizeof(Class)); // Allocate memory
 auto instance = new(instanceBlob)Class{}; // Initialize via constructor
 instance.~Class(); // Destroy via destructor
 std::free(instanceBlob); // Deallocate the memory

যদিও উপরেরটি বৈধ, এটি একটি নতুন অপারেটরের মাধ্যমেও করা যেতে পারে। std::vectorএটির জন্য একটি ভাল উদাহরণ।

পরিশেষে, আমরা এখনো রুমে হাতি আছে: C। আপনার যদি এমন সি-লাইব্রেরি নিয়ে কাজ করতে হয় যেখানে মেমরিটি সি ++ কোডে বরাদ্দ হয়ে যায় এবং সি কোডে (বা অন্য উপায়ে) মুক্ত হয় তবে আপনাকে ম্যালোক / ফ্রি ব্যবহার করতে বাধ্য করা হবে।

আপনি যদি এই ক্ষেত্রে থাকেন তবে ভার্চুয়াল ফাংশন, সদস্য ফাংশন, ক্লাসগুলি সম্পর্কে ভুলে যান ... কেবলমাত্র এতে POD সহ স্ট্রাক্টের অনুমতি রয়েছে।

নিয়মের কিছু ব্যতিক্রম:

  • আপনি উন্নত ডেটা স্ট্রাকচার সহ একটি স্ট্যান্ডার্ড লাইব্রেরি লিখছেন যেখানে malloc উপযুক্ত
  • আপনাকে বড় পরিমাণে মেমরি বরাদ্দ করতে হবে (10 জিবি ফাইলের মেমরি অনুলিপিটিতে?)
  • আপনার নির্দিষ্ট সরঞ্জাম ব্যবহার করতে বাধা দেওয়ার সরঞ্জাম রয়েছে
  • আপনার একটি অসম্পূর্ণ প্রকার সংরক্ষণ করতে হবে

6

কিছু জিনিস রয়েছে যা newতা mallocকরে না:

  1. new object অবজেক্টটির কনস্ট্রাক্টরকে ফোন করে বস্তুটি তৈরি করে
  2. new বরাদ্দ মেমরি টাইপকাস্টিং প্রয়োজন হয় না।
  3. এটি বরাদ্দ করার জন্য প্রচুর পরিমাণে মেমরির প্রয়োজন হয় না, বরং এটি নির্মাণের জন্য বেশ কয়েকটি অবজেক্টের প্রয়োজন।

সুতরাং, আপনি যদি ব্যবহার করেন mallocতবে আপনার উপরের বিষয়গুলি স্পষ্টভাবে করা দরকার যা সর্বদা ব্যবহারিক নয়। অতিরিক্তভাবে, অতিরিক্ত newলোড করা যায় কিন্তু mallocহতে পারে না।


5

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

যাই হোক না কেন, আমি দেখতে পাচ্ছি না কেন আপনি উভয়ই ব্যবহার করবেন না (যদি আপনি আপনার ম্যালসড মেমরিটি মুক্ত করেন এবং নতুন দিয়ে বরাদ্দকৃত বিষয়গুলি মুছুন) যদি গতি বৃদ্ধির সুযোগ নিতে পারে (কখনও কখনও উল্লেখযোগ্য একটি, আপনি যদি বড় অ্যারেগুলি পুনরায় প্রকাশ করছেন তবে রিলোক আপনাকে দিতে পারে P

যদিও আপনার এটির প্রয়োজন না হলে আপনার সি ++ এ নতুন / মুছে ফেলা উচিত।


3

আপনার যদি সি কোড থাকে তবে আপনি সি ++ তে পোর্ট করতে চান, আপনি এতে কোনও ম্যালোক () কল ছেড়ে যেতে পারেন। যে কোনও নতুন সি ++ কোডের জন্য, আমি পরিবর্তে নতুন ব্যবহারের পরামর্শ দেব।


3

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


2

new স্ট্রাক্টের ডিফল্ট মানগুলিকে আরম্ভ করবে এবং এর মধ্যে উল্লেখগুলি সঠিকভাবে নিজের সাথে লিঙ্ক করবে।

যেমন

struct test_s {
    int some_strange_name = 1;
    int &easy = some_strange_name;
}

সুতরাং new struct test_sএকটি কার্যনির্বাহী রেফারেন্স সহ একটি প্রাথমিক কাঠামো ফিরে আসবে, যখন malloc'ed সংস্করণটির কোনও ডিফল্ট মান থাকে না এবং অভ্যন্তরীণ উল্লেখগুলি আরম্ভ হয় না।


1

একটি নিম্ন দৃষ্টিকোণ থেকে, নতুন মেমরি দেওয়ার আগে সমস্ত মেমরি শুরু করবে যখন malloc মেমরির মূল বিষয়বস্তু রাখবে।


4
নতুন সাধারণভাবে স্মৃতিশক্তি আরম্ভ করে না, যদিও এটি হওয়ার উপায় রয়েছে: এ সম্পর্কে একটি আলোচনার জন্য stackoverflow.com/questions/2204176/… দেখুন ।
wjl

0

নিম্নলিখিত দৃশ্যে, আমরা নতুনটি ব্যবহার করতে পারি না কারণ এটি কনস্ট্রাক্টরকে কল করে।

class  B  {
private:
    B *ptr;
    int x;
public:
    B(int n)  {
        cout<<"B: ctr"<<endl;
        //ptr = new B;  //keep calling ctr, result is segmentation fault
        ptr = (B *)malloc(sizeof(B));
        x = n;
        ptr->x = n + 10;
    }
    ~B()  {
        //delete ptr;
        free(ptr);
        cout<<"B: dtr"<<endl;
    }
};

0

newএবং deleteঅপারেটরদের ক্লাস এবং কাঠামো উপর কাজ করতে পারে, যেহেতু mallocএবং freeশুধুমাত্র মেমরি যা নিক্ষেপ করা প্রয়োজন ব্লক সঙ্গে কাজ করে।

ব্যবহার করা new/deleteআপনার কোডটিকে উন্নত করতে সহায়তা করবে কারণ আপনাকে প্রয়োজনীয় ডেটা স্ট্রাকচারে বরাদ্দ মেমরির প্রয়োজন হবে না।


0

নতুন / মুছে ফেলার পরিবর্তে ম্যালোক / ফ্রি ব্যবহার বিবেচনা করার ক্ষেত্রে বিরল ক্ষেত্রে হ'ল সি ++ এ রিলোকের অনুরূপ কোনও কার্যকারিতা না থাকায় রিলোক ব্যবহার করে (সরল পডের ধরণ, অবজেক্ট নয়) পুনর্নির্মাণ করা হয় (যদিও এটি ব্যবহার করে করা যেতে পারে) আরও সি ​​++ পদ্ধতির)।


-4

malloc () সিটিতে মেমোরি নির্ধারণের জন্য ব্যবহৃত হয় যখন একই কাজটি নতুন () দ্বারা সি ++ এ করা হয়। সুতরাং আপনি 2 টি ভাষার কোডিং কনভেনশনগুলি মিশ্রণ করতে পারবেন না। আপনি কলোক এবং ম্যালোক () এর মধ্যে পার্থক্য জানতে চাইলে ভাল হবে would


2
আপনি করতে পারেন (কিন্তু প্রায় সবসময় করা উচিত নয়) ব্যবহার mallocC ++।
ইন্টারজয়

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