"নতুন বসানো" এর জন্য কী কী ব্যবহার রয়েছে?


410

এখানে কেউ কি কখনও সি ++ এর "প্লেসমেন্ট নতুন" ব্যবহার করেছেন? যদি তাই হয় তবে কিসের জন্য? এটি আমার কাছে মনে হচ্ছে এটি কেবল মেমরি-ম্যাপযুক্ত হার্ডওয়্যারে কার্যকর হবে।


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


@ হেলো গুডবি, আকর্ষণীয়! নিবন্ধটি আপনার লিঙ্ক, কেন আপনি শুধু ব্যবহার করতে পারবেন না p = ptএবং ব্যবহার নিয়োগ অপারেটর Pointপরিবর্তে করছেন new(&p) Point(pt)? আমি দুজনের মধ্যে পার্থক্য অবাক। operator=পয়েন্টে পূর্বের কলটি হবে, যদিও পরবর্তীকালের কপির কনস্ট্রাক্টর কল করবে Point? তবে কেন আমি একজনের থেকে অপরটির চেয়ে ভাল তা এখনও পরিষ্কার নয়।
আন্দ্রে-নিকুলি পেট্রে

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

@ অ্যান্ড্রে-নিকুলিপেট্রে আসলে, আমি উইকিপিডিয়া নিবন্ধে উদাহরণটি বেশ খারাপ দেখতে পেয়েছি , কারণ এটি কেবল ধরে নিয়েছে যে কোনও পূর্ববর্তী বস্তু বিদ্যমান নেই এবং তাদের একটি নির্মাণ করা প্রয়োজন। U::operator=সবেমাত্র ডেকে এলে এটি হয় না ।
হ্যালো গুডবাই

উত্তর:


364

প্লেসমেন্ট নতুন আপনাকে ইতিমধ্যে বরাদ্দ মেমরিতে একটি অবজেক্ট তৈরি করতে দেয়।

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

ডেভএক্স একটি ভাল উদাহরণ দেয় :

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

char *buf  = new char[sizeof(string)]; // pre-allocated buffer
string *p = new (buf) string("hi");    // placement new
string *q = new string("hi");          // ordinary heap allocation

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

স্থান নির্ধারণ নতুন

মেমোরি বাফার ব্যবহার করে এমন প্রতিটি বস্তুর আপনার ডিএলোকট করা উচিত নয়। পরিবর্তে আপনার [মূল] বাফারটি কেবল মুছতে হবে। এরপরে আপনাকে নিজের ক্লাসের ডেস্ট্রাক্টরকে ম্যানুয়ালি কল করতে হবে। এ সম্পর্কে একটি ভাল পরামর্শের জন্য, দয়া করে স্ট্রাস্ট্রাপের প্রায়শই জিজ্ঞাসিত প্রশ্নাগুলি দেখুন: "প্লেসমেন্ট মোছা" আছে কি ?


54
কন্টেইনার অবজেক্টগুলি (ভেক্টরের মতো) কার্যকরভাবে কার্যকর করার জন্য আপনার এই বৈশিষ্ট্যটির প্রয়োজন হওয়ায় এটি অবহেলা করা হয়নি। আপনি যদি নিজের কন্টেইনারটি তৈরি না করে থাকেন তবে আপনাকে এই বৈশিষ্ট্যটি ব্যবহার করার দরকার নেই।
মার্টিন ইয়র্ক

26
# অন্তর্ভুক্ত <স্মৃতি> মনে রাখাও খুব গুরুত্বপূর্ণ, অন্যথায় আপনি কিছু প্ল্যাটফর্মের কিছু ভয়াবহ মাথাব্যথার মধ্যে চলে যেতে পারেন যা স্বয়ংক্রিয়ভাবে স্থান নির্ধারণকে নতুন করে স্বীকৃতি দেয় না
রামন জারাজুয়া বি।

22
কঠোরভাবে, delete[]মূল charবাফারটি কল করা এটি অপরিজ্ঞাত আচরণ । প্লেসমেন্ট ব্যবহার newকরে মূল charস্টোরেজগুলির স্টোরেজটি পুনরায় ব্যবহার করে তার জীবনকাল শেষ হয়েছে । আপনি যদি এখন delete[] bufঅবজেক্ট (গুলি) এর গতিশীল প্রকারকে কল করেন তবে তাদের স্থিতিশীল টাইপের সাথে আর মেলে না তাই আপনার অপরিজ্ঞাত আচরণ রয়েছে। স্থাপনের মাধ্যমে ব্যবহারের জন্য অন্তর্নিহিত কাঁচা মেমরির বরাদ্দ করার জন্য এটি ব্যবহার operator new/ আরও বেশি সামঞ্জস্যপূর্ণ । operator deletenew
সিবি বেইলি

31
আমি অবশ্যই
পেস মেকারে হিপটি

15
@ রামনজারাজুয়া ভুল শিরোনাম, এটি #include <new>
বিট 2 শিফট

63

আমরা এটি কাস্টম মেমরি পুল সহ ব্যবহার করি। কেবল একটি স্কেচ:

class Pool {
public:
    Pool() { /* implementation details irrelevant */ };
    virtual ~Pool() { /* ditto */ };

    virtual void *allocate(size_t);
    virtual void deallocate(void *);

    static Pool::misc_pool() { return misc_pool_p; /* global MiscPool for general use */ }
};

class ClusterPool : public Pool { /* ... */ };
class FastPool : public Pool { /* ... */ };
class MapPool : public Pool { /* ... */ };
class MiscPool : public Pool { /* ... */ };

// elsewhere...

void *pnew_new(size_t size)
{
   return Pool::misc_pool()->allocate(size);
}

void *pnew_new(size_t size, Pool *pool_p)
{
   if (!pool_p) {
      return Pool::misc_pool()->allocate(size);
   }
   else {
      return pool_p->allocate(size);
   }
}

void pnew_delete(void *p)
{
   Pool *hp = Pool::find_pool(p);
   // note: if p == 0, then Pool::find_pool(p) will return 0.
   if (hp) {
      hp->deallocate(p);
   }
}

// elsewhere...

class Obj {
public:
   // misc ctors, dtors, etc.

   // just a sampling of new/del operators
   void *operator new(size_t s)             { return pnew_new(s); }
   void *operator new(size_t s, Pool *hp)   { return pnew_new(s, hp); }
   void operator delete(void *dp)           { pnew_delete(dp); }
   void operator delete(void *dp, Pool*)    { pnew_delete(dp); }

   void *operator new[](size_t s)           { return pnew_new(s); }
   void *operator new[](size_t s, Pool* hp) { return pnew_new(s, hp); }
   void operator delete[](void *dp)         { pnew_delete(dp); }
   void operator delete[](void *dp, Pool*)  { pnew_delete(dp); }
};

// elsewhere...

ClusterPool *cp = new ClusterPool(arg1, arg2, ...);

Obj *new_obj = new (cp) Obj(arg_a, arg_b, ...);

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


1
হাঁ। আমরা সে সম্পর্কে মোটামুটি চালাক হয়ে উঠি তবে এটি এই প্রশ্নের বাইরে বিষয় নয়।
ডন ওয়েকফিল্ড

2
@jdkoftinoff আপনার কি একটি আসল কোড নমুনার সাথে কোনও লিঙ্ক আছে? আমার জন্য বেশ আকর্ষণীয় বলে মনে হচ্ছে!
ভিক্টর

@ ডোনওয়েকফিল্ড আপনি কীভাবে এই পুলটিতে সারিবদ্ধতা পরিচালনা করবেন? আপনার allocate()কোথাও যুক্তি হিসাবে প্রান্তিককরণটি পাস করা উচিত নয় ?
মিখাইল ভাসিলিভ

1
@ মিখাইলভ্যাসিলিভ, বাস্তব বাস্তবায়নের ক্ষেত্রে আপনি অবশ্যই তা পরিচালনা করবেন। উদাহরণ কোড।
ডন ওয়েকফিল্ড

যদি প্লেসমেন্টটি একটি অবৈধ ঠিকানা হয় তবে 0x0 বলুন?
চার্লি 4

51

আপনি যদি প্রাথমিককরণ থেকে বরাদ্দ আলাদা করতে চান তবে এটি কার্যকর। এসটিএল ধারক উপাদান তৈরি করতে প্লেসমেন্ট নতুন ব্যবহার করে।


35

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

আমি যা করতে পারি তা হ'ল মেমরির একটি বিশাল অংশ (ক্লাসের জন্য প্রয়োজনীয় যে পরিমাণ পরিমাণ রাখা যথেষ্ট)) তারপরে, আমি যখন রানটাইমগুলিতে জিনিসগুলি কীভাবে তৈরি করব তা একবার নির্ধারণ করি, ঠিক যেখানে প্লেসগুলি চাই সেখানে অবজেক্ট তৈরি করতে নতুন প্লেসমেন্ট ব্যবহার করা যেতে পারে। আমি জানি যে পরিস্থিতি আমি এটি ব্যবহার করেছিলাম তা হ'ল ভিন্নজাতীয় বিজ্ঞপ্তি বাফার তৈরি করতে সহায়তা করা ।

এটি অবশ্যই হৃদয়ের ক্লান্তির জন্য নয়, তবে এ কারণেই তারা এর সিনট্যাক্সটি দারুণভাবে প্রকাশ করেছেন।


হাই টেড, আপনি যে সমাধানটি পেয়েছেন সে সম্পর্কে আপনি আরও ভাগ করে নিতে পারেন। আমি পূর্ব নির্ধারিত সমাধানের বিষয়ে ভাবছি তবে খুব বেশি অগ্রগতি পাই নি। তুমাকে অগ্রিম ধন্যবাদ!
ভিয়েতনাম

1
ঠিক আছে, আসল হেট্রোজেনিয়াস বিজ্ঞপ্তি বাফার কোডটি ডান হওয়ার পক্ষে সত্যই জটিল অংশ ছিল। প্যালসেন্ট নতুনটি কিছুটা গুরুতর দেখায় তবে তুলনা করে এটি মোটেই কোনও ঝামেলা ছিল না।
টেড

26

আমি এটি বরাদ্দ () এর মাধ্যমে স্ট্যাকের উপর বরাদ্দ করা অবজেক্টগুলি তৈরি করতে ব্যবহার করেছি।

নির্লজ্জ প্লাগ: আমি এটি সম্পর্কে এখানে ব্লগ করেছি ।


আকর্ষণীয় নিবন্ধ, তবে আমি নিশ্চিত না যে এই ওভারটি ব্যবহারের সুবিধাটি আমি বুঝতে পেরেছি boost::array। আপনি কি কিছুটা প্রসারিত করতে পারেন?
গ্রাহামস

Boost :: অ্যারে সংকলন-সময় ধ্রুবক হতে অ্যারের আকার প্রয়োজন। এটির সীমাবদ্ধতা নেই।
ফেরুক্সিও

2
@ ফেরুচ্চিও এটি দুর্দান্ত, উদাহরণস্বরূপ যদি x + 1 পাস করা হয় তবে আপনি এটি আকার (প্রকার) * x + 1 এ প্রসারিত করবেন যা ভুল হবে। আপনার ম্যাক্রোটিকে আরও সুরক্ষিত করতে আপনার ব্রাকেট করা দরকার।
বেনজ

যদি আপনার সমস্ত বস্তুর উপর ডেস্ট্রাক্টরদের কল করতে হয় তবে একটি ব্যতিক্রম ছোঁড়া হলে বরাদ্দ সহ আমার ব্যবহার করা বিপজ্জনক বলে মনে হয়।
ক্যাশকো

14

প্রধান গীক: বিঙ্গো! আপনি এটি সম্পূর্ণরূপে পেয়েছেন - এটি ঠিক এটির জন্য উপযুক্ত। অনেক এম্বেড থাকা পরিবেশে, বাহ্যিক প্রতিবন্ধকতা এবং / বা সামগ্রিক ব্যবহারের দৃশ্যাবলী প্রোগ্রামারকে কোনও বস্তুর বরাদ্দকে তার শুরু থেকে আলাদা করতে বাধ্য করে। একসাথে লম্পট, সি ++ এটিকে "ইনস্ট্যান্টেশন" বলে; তবে যখনই নির্মাণকের ক্রিয়াটি স্পষ্টভাবে ডাইনামিক বা স্বয়ংক্রিয় বরাদ্দের ব্যতীত ডেকে আনা উচিত, প্লেসমেন্ট নতুন এটি করার উপায় do এটি একটি গ্লোবাল সি ++ অবজেক্টকে সনাক্ত করার সঠিক উপায় যা কোনও হার্ডওয়্যার উপাদান (মেমরি-ম্যাপযুক্ত I / O) এর ঠিকানায় পিন করা আছে, বা কোনও স্থিতিক অবজেক্টের জন্য, যে কোনও কারণেই অবশ্যই একটি নির্দিষ্ট ঠিকানায় থাকতে হবে।


12

আমি এটি একটি ভেরিয়েন্ট শ্রেণি তৈরি করতে ব্যবহার করেছি (অর্থাত এমন একটি বস্তু যা একক মানকে বিভিন্ন ধরণের এক হতে পারে যা উপস্থাপন করতে পারে)।

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

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


এরম, নন-পিওডি ডেটাটাইপগুলি কোনও ইউনিয়নের মধ্যে ঘোষণা করা যেতে পারে, যতক্ষণ আপনি ইউনিয়ন কর্টর সরবরাহ করেন - এবং আরে - সেই কর্টর সম্ভবতnew তার নন-পিওডি সাবক্লাস শুরু করার জন্য প্লেসমেন্ট ব্যবহার করবে । রেফ: স্ট্যাকওভারফ্লো. com / a / 33289972 / 2757035 নির্বিচারে বড় বাইট অ্যারে ব্যবহার করে এই চাকাটিকে পুনরায় উদ্ভাবন করা অ্যাক্রোব্যাটিক্সের একটি চিত্তাকর্ষক টুকরা তবে সম্পূর্ণ অপ্রয়োজনীয় বলে মনে হচ্ছে, সুতরাং, আমি কী মিস করেছি? :)
আন্ডারস্কোর_২০

6
আপনি সি ++ এর সমস্ত সংস্করণ সি ++ 11 এর আগে মিস করেছেন, অনেক ক্ষেত্রে এখনও সমর্থন করা দরকার। :)
জেরেমি ফ্রাইজনার

10

সিরিয়ালাইজ করার সময় প্লেসমেন্ট নতুনটিও খুব কার্যকর ( সি ++ এর দশ বছরে এটি কেবলমাত্র দ্বিতীয় ক্ষেত্রে আমার জন্য নতুন প্লেসমেন্টের প্রয়োজন (তৃতীয়ত যদি আপনি সাক্ষাত্কার অন্তর্ভুক্ত করেন :))।


9

আপনি যখন গ্লোবাল বা স্ট্যাটিক্যালি বরাদ্দকৃত স্ট্রাকচারগুলি পুনরায় শুরু করতে চান তখন এটি দরকারী useful

পুরানো সি উপায় ব্যবহার করছিল memset() উপায়টি সমস্ত উপাদানকে 0 এ সেট জন্য আপনি ভিটিবেল এবং কাস্টম অবজেক্ট কনস্ট্রাক্টরের কারণে C ++ এ এটি করতে পারবেন না।

তাই আমি মাঝে মাঝে নিম্নলিখিত ব্যবহার করি

 static Mystruct m;

 for(...)  {
     // re-initialize the structure. Note the use of placement new
     // and the extra parenthesis after Mystruct to force initialization.
     new (&m) Mystruct();

     // do-some work that modifies m's content.
 }

1
সেভাবে পুনরায় সূচনা করার আগে কি আপনাকে সংশ্লিষ্ট ধ্বংসের দরকার হবে না?
হেড গীক

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

1
এমনকি সিতে, সমস্ত বিটকে 0 তে সেট করা কেবলমাত্র অবিচ্ছেদ্য প্রকারের জন্য 0 এর উপস্থাপনের গ্যারান্টিযুক্ত, অন্য ধরণের নয় (নাল পয়েন্টারটিতে শূন্য নয় এমন উপস্থাপনা থাকতে পারে)।
কৌতূহলী

@ কুরিয়াসগুই - আদিম ধরণের জন্য আপনি সঠিক (এটি প্রোগ্রামটি অনুমানযোগ্য করে তুলবে যা ডিবাগিংয়ের সময় আসে একটি সুবিধা)। তবে সি ++ ডেটাটাইপগুলিতে তাদের কনস্ট্রাক্টর দৌড়বে (জায়গায়) এবং সঠিকভাবে শুরু করা হবে properly
নিমরোডম

9

এটি আসলে কোনও ধরণের ডেটা স্ট্রাকচার বাস্তবায়নের জন্য প্রয়োজনীয় যা sertedোকানো উপাদানগুলির সংখ্যার জন্য ন্যূনতম প্রয়োজনের চেয়ে বেশি মেমরি বরাদ্দ করে (যেমন, কোনও সময়ে কোনও নোড বরাদ্দকৃত লিঙ্কযুক্ত কাঠামো ছাড়া অন্য কিছু)।

নিন পাত্রে পছন্দ unordered_map, vectorঅথবা deque। প্রতিটি একক সন্নিবেশের জন্য একটি গাদা বরাদ্দ প্রয়োজন এড়াতে এগুলি এখন পর্যন্ত যে উপাদানগুলি আপনি inোকালেন তার জন্য ন্যূনতমভাবে প্রয়োজনীয় মেমরির পরিমাণ বেশি বরাদ্দ করে। চলুন ব্যবহার করা যাকvector সহজ উদাহরণ হিসাবে করা ।

যখন তুমি কর:

vector<Foo> vec;

// Allocate memory for a thousand Foos:
vec.reserve(1000);

... এটি আসলে হাজার হাজার ফুস তৈরি করে না। এটি কেবল তাদের জন্য মেমরির বরাদ্দ / সংরক্ষণ করে। যদি vectorএখানে प्लेসমেন্ট নতুন ব্যবহার না করা হয় তবে এটি ডিফল্ট-নির্মাণ হবেFoos পুরো জায়গা জুড়ে পাশাপাশি তাদের ধ্বংসকারীদের অনুরোধ করতে হবে এমনকি এমন উপাদানগুলির জন্য এমনকি আপনি প্রথম স্থানে প্রবেশ করেননি।

বরাদ্দ! = নির্মাণ, বিনামূল্যে! = ধ্বংস

উপরের মতো অনেকগুলি ডেটা স্ট্রাকচার বাস্তবায়নের জন্য সাধারণভাবে বলতে গেলে, আপনি মেমরি বরাদ্দকরণ এবং উপাদানগুলি একটি অবিভাজ্য জিনিস হিসাবে নির্ধারণ করতে পারবেন না এবং আপনি একইভাবে মেমরি মুক্ত করে এবং উপাদানগুলিকে একটি অবিভাজ্য জিনিস হিসাবে চিকিত্সা করতে পারবেন না।

অযৌক্তিকভাবে বাম এবং ডানদিকে অতিমাত্রায় আহ্বানকারী কনস্ট্রাক্টর এবং ডেস্ট্রাক্টরদের এড়াতে এই ধারণাগুলির মধ্যে পৃথকীকরণ করতে হবে এবং এজন্যই স্ট্যান্ডার্ড লাইব্রেরি এই ধারণাটিকে পৃথক করে std::allocator(যা মেমরি * বরাদ্দ / মুক্ত করার সময় উপাদানগুলি নির্মাণ বা ধ্বংস করে না) থেকে দূরে থাকে from যে পাত্রে এটি ব্যবহার করা হয় সেগুলি প্ল্যাসমেন্ট নতুন ব্যবহার করে ম্যানুয়ালি উপাদান তৈরি করে এবং ডিস্ট্রাক্টরের স্পষ্ট আহবান ব্যবহার করে উপাদানগুলিকে ম্যানুয়ালি নষ্ট করে।

  • আমি এর নকশাকে ঘৃণা করি std::allocatorতবে এটি আলাদা বিষয় আমি রেটিং এড়ানো এড়াতে চাই। :-D

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

স্বাভাবিকভাবেই যদি আপনি কাস্টম বরাদ্দকারীদের সাথে নিখরচায় পৃথকভাবে অবজেক্টগুলিকে বরাদ্দ দেওয়ার জন্য কাজ করেন, তবে আপনি সাধারণত placement newএটির মতো ব্যবহার করতে চান (ব্যতিক্রমী-সুরক্ষা বা আরআইআইআই-তে বিরক্ত করে না এমন মৌলিক উদাহরণ):

Foo* foo = new(free_list.allocate()) Foo(...);
...
foo->~Foo();
free_list.free(foo);

8

এটি কার্যকর যদি আপনি কোনও কার্নেল তৈরি করে থাকেন - আপনি ডিস্ক বা পৃষ্ঠাগুলি থেকে পড়া কার্নেল কোডটি কোথায় রাখবেন? কোথায় যেতে হবে তা আপনার জানতে হবে।

বা অন্য কোনও ক্ষেত্রে, খুব বিরল পরিস্থিতিতে যেমন আপনার যখন বরাদ্দ কক্ষ বেশি থাকে এবং একে অপরের পিছনে কয়েকটি কাঠামো স্থাপন করতে চান। অফসেটফ () অপারেটরের প্রয়োজন ছাড়াই এগুলি এগুলি প্যাক করা যায়। যদিও এর জন্য অন্যান্য কৌশলও রয়েছে।

আমি আরও বিশ্বাস করি যে কিছু এসটিএল বাস্তবায়ন স্ট্যান্ড :: ভেক্টরের মতো নতুন প্লেসমেন্ট ব্যবহার করে। তারা 2 elements n উপাদানগুলির জন্য সেভাবে ঘর বরাদ্দ করে এবং সর্বদা পুনর্বিবেচনার প্রয়োজন হয় না।


মেমরি বরাদ্দ হ্রাস হ'ল এটির ব্যবহারের একটি প্রাথমিক কারণ, পাশাপাশি ডিস্কের বাইরে অবজেক্ট লোড করার মতো "কৌশল"
বামটি

আমি সি ++ তে লেখা কোনও কার্নেল সম্পর্কে জানি না; বেশিরভাগ কার্নেলগুলি সরাসরি
সিটিতে

8
যে অপারেটিং সিস্টেমের সাহায্যে আমি ওএস বেসিকগুলি
mstrobl

8

আমি মনে করি এটি কোনও উত্তরের দ্বারা হাইলাইট করা হয়নি তবে নতুন স্থান নির্ধারণের জন্য আরেকটি ভাল উদাহরণ এবং ব্যবহার হ'ল মেমরি বিভাজন হ্রাস করা (মেমরি পুল ব্যবহার করে)। এটি এম্বেড করা এবং উচ্চ প্রাপ্যতা সিস্টেমে বিশেষভাবে কার্যকর। এই শেষ ক্ষেত্রে এটি বিশেষভাবে গুরুত্বপূর্ণ কারণ যে সিস্টেমে 24/365 দিন চলতে হয় তার জন্য কোনও খণ্ডন না হওয়া খুব গুরুত্বপূর্ণ। এই সমস্যার স্মৃতি ফাঁস হওয়ার কোনও সম্পর্ক নেই।

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

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

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



7

আমি এটিকে মেমরি ম্যাপযুক্ত ফাইলগুলির সাথে অবজেক্টগুলি সঞ্চয় করার জন্য ব্যবহার করেছি।
সুনির্দিষ্ট উদাহরণটি ছিল একটি চিত্রের ডেটাবেস যা প্রচুর পরিমাণে বৃহত চিত্র (মেমরির সাথে ফিট করতে পারে তার চেয়ে বেশি) প্রসেস করে।


7

আমি এটি "গতিশীল প্রকার" পয়েন্টার ("হুডের নীচে" বিভাগে) জন্য সামান্য পারফরম্যান্স হ্যাক হিসাবে দেখেছি :

তবে এখানে ছোট কৌশলগুলির জন্য দ্রুত কার্য সম্পাদন করার জন্য আমি যে কৌশলটি ব্যবহার করেছি তা হ'ল: যদি ধারণকৃত মানটি শূন্যের ভিতরে * ফিট করতে পারে তবে আমি আসলে কোনও নতুন বিষয় বরাদ্দ করতে বিরক্ত করি না, আমি এটিকে প্লেসমেন্টে নতুন করে প্লেসমেন্ট ব্যবহার করে জোর করে থাকি ।


মানাগুলি হ'ল যদি কোন শূন্যের অভ্যন্তরে ফিট করতে পারে তবে তার অর্থ কী? কোনও পয়েন্টার টাইপ শূন্য * করতে এটি সর্বদা সম্ভব। আপনি কি আমাদের কিছু উদাহরণ দেখাতে পারেন?
অনুরাগ 86

@ অনুরাগ 86: আমার 64 বিট মেশিনে, এ void* 8 বাইট নেয়। void*এক বাইটে আট-বাইট পয়েন্ট করা একটু নির্বোধ bool। কিন্তু এটি আসলে আচ্ছাদন করার জন্য সম্পূর্ণরূপে সম্ভব boolউপর void*অনেকটা মতো union { bool b; void* v }। আপনার কিছু উপায় জানতে হবে যে আপনি যেটিকে ডাকলেন void*সেটি আসলে একটি bool(বা ক short, বা এ float, ইত্যাদি)। আমি যে নিবন্ধটির সাথে লিঙ্ক করেছি তাতে এটি কীভাবে করা যায় তা বর্ণনা করা হয়েছে। এবং, মূল প্রশ্নের উত্তর দেওয়ার জন্য, স্থান নির্ধারণ newএমন বৈশিষ্ট্য যা একটি bool(বা অন্য ধরণের) তৈরি করতে ব্যবহৃত হয় যেখানে একটি void*প্রত্যাশিত হয় (ক্যাসেটগুলি পরে মান পেতে / পরিবর্তন করতে ব্যবহৃত হয়)।
ম্যাক্স ল্যাববার্ট

@ অনুরাগ:।: এটি একই জিনিস নয়, তবে আপনি ট্যাগ পয়েন্টারগুলিতে আগ্রহী হতে পারেন ( en.wikedia.org/wiki/Tagged_pointer )।
ম্যাক্স ল্যাবার্ট

6

আমি এটি নেটওয়ার্ক থেকে প্রাপ্ত বার্তাগুলি সহ মেমরির ভিত্তিতে অবজেক্ট তৈরি করতে ব্যবহার করেছি।


5

সাধারণত, 'নতুন নতুন' এর বরাদ্দ ব্যয় থেকে মুক্তি পেতে প্লেসমেন্ট নতুন ব্যবহার করা হয়।

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



4

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

আমি এটি একই ধরণের ব্যবহার করেছি, যদিও এটি প্রায়শই আসে না। যদিও এটি সি ++ টুলবক্সের জন্য একটি দরকারী সরঞ্জাম।


4

স্ক্রিপ্ট ইঞ্জিনগুলি এটিকে স্থানীয় ইন্টারফেসে স্ক্রিপ্ট থেকে নেটিভ অবজেক্ট বরাদ্দ করতে ব্যবহার করতে পারে। উদাহরণস্বরূপ অ্যাঞ্জেলস্ক্রিপ্ট (www.angelcode.com/angelscript) দেখুন।


3

এক্সএল প্রজেক্টের fx.h ফাইলটি http://xll.codeplex.com এ দেখুন এটি এটি অ্যারেগুলির জন্য "অযাচিত চাওমিনিস " সমাধান করে যা তাদের সাথে তাদের মাত্রাগুলি প্রায় বহন করতে পছন্দ করে।

typedef struct _FP
{
    unsigned short int rows;
    unsigned short int columns;
    double array[1];        /* Actually, array[rows][columns] */
} FP;

2

সি ++ ইন-প্লেস কনস্ট্রাক্টরের জন্য হত্যাকারী ব্যবহার এখানে রয়েছে: ক্যাশে লাইনে সারিবদ্ধকরণ, পাশাপাশি 2 টি সীমানার অন্যান্য শক্তি। 5 বা তারও কম একক-চক্র নির্দেশাবলী সহ 2 সীমানার যেকোন পাওয়ারে আমার অতি-দ্রুত পয়েন্টার সারিবদ্ধকরণ অ্যালগরিদম এখানে রয়েছে :

/* Quickly aligns the given pointer to a power of two boundary IN BYTES.
@return An aligned pointer of typename T.
@brief Algorithm is a 2's compliment trick that works by masking off
the desired number in 2's compliment and adding them to the
pointer.
@param pointer The pointer to align.
@param boundary_byte_count The boundary byte count that must be an even
power of 2.
@warning Function does not check if the boundary is a power of 2! */
template <typename T = char>
inline T* AlignUp(void* pointer, uintptr_t boundary_byte_count) {
  uintptr_t value = reinterpret_cast<uintptr_t>(pointer);
  value += (((~value) + 1) & (boundary_byte_count - 1));
  return reinterpret_cast<T*>(value);
}

struct Foo { Foo () {} };
char buffer[sizeof (Foo) + 64];
Foo* foo = new (AlignUp<Foo> (buffer, 64)) Foo ();

এখন এটি কেবল আপনার মুখে হাসি দেয় না (:-))। I ♥♥♥ C ++ 1x

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