অ্যারে সহ ইউনিক_পিটারের কোনও ব্যবহার আছে?


238

std::unique_ptr উদাহরণস্বরূপ অ্যারেগুলির জন্য সমর্থন রয়েছে:

std::unique_ptr<int[]> p(new int[10]);

তবে এটা কি দরকার? সম্ভবত এটি ব্যবহার করা আরও সুবিধাজনক std::vectorবা std::array

আপনি কি এই নির্মাণের জন্য কোনও ব্যবহার খুঁজে পান?


6
সম্পূর্ণতার জন্য, আমি উল্লেখ করতে হবে যে সেখানে নেই std::shared_ptr<T[]>, তবে এটি থাকা উচিত এবং সম্ভবত কেউ C ++ 14 এ থাকবেন যদি কেউ প্রস্তাব উত্থাপন করতে বিরক্ত হতে পারে। গড় সময়ে, সবসময় আছে boost::shared_array
ছদ্মনাম

13
std::shared_ptr<টি []> এখন সি ++ 17 এ রয়েছে।

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

উত্তর:


256

কিছু লোকের ব্যবহারের বিলাসিতা নেই std::vector, এমনকি বরাদ্দকারীদেরও। কিছু লোকের গতিশীল আকারের অ্যারে প্রয়োজন, তাই std::arrayবাইরে। এবং কিছু লোক তাদের কোডগুলি অন্য কোড থেকে পান যা অ্যারে ফিরিয়ে দেয় বলে পরিচিত; এবং সেই কোডটি কোনও vectorবা কিছু ফেরত দেওয়ার জন্য পুনরায় লেখা হবে না ।

অনুমতি দিয়ে unique_ptr<T[]>, আপনি সেই প্রয়োজনগুলি পরিবেশন করেন।

সংক্ষেপে, আপনি unique_ptr<T[]>যখন প্রয়োজন তখন ব্যবহার করুন । যখন বিকল্পগুলি কেবল আপনার জন্য কাজ করে না। এটি সর্বশেষ অবলম্বনের একটি সরঞ্জাম।


27
@ ননসেন্সএইটএল: আমি নিশ্চিত না যে "কিছু লোকের এটি করার অনুমতি নেই" এর কোন অংশটি আপনাকে অন্তর্ভুক্ত করে। কিছু প্রকল্পের খুব নির্দিষ্ট প্রয়োজনীয়তা থাকে এবং এর মধ্যে "আপনি ব্যবহার করতে পারবেন না" হতে পারে vector। সেগুলি যুক্তিসঙ্গত প্রয়োজনীয়তাগুলি কিনা সে বিষয়ে আপনি তর্ক করতে পারেন, তবে আপনি যে তা বিদ্যমান তা অস্বীকার করতে পারবেন না ।
নিকল বোলাস

21
বিশ্বে কোনও কারণ নেই যে কেউ std::vectorযদি ব্যবহার করতে পারে তবে কেন ব্যবহার করতে সক্ষম হবে না std::unique_ptr
মাইলস রাউট

66
ভেক্টর ব্যবহার না করার একটি কারণ এখানে রয়েছে: মাপের (স্টাড :: ভেক্টর <চর>) == 24; যাও sizeof (এসটিডি :: unique_ptr <গৃহস্থালির কাজ []>) == 8
Arvid

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

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

124

এখানে ট্রেড অফস রয়েছে এবং আপনি যা সমাধান চান তার সাথে মিলে যা সমাধান বেছে নিন। আমার মাথার উপরে:

প্রাথমিক আকার

  • vectorএবং unique_ptr<T[]>রান-টাইমে আকার নির্দিষ্ট করার অনুমতি দিন
  • array শুধুমাত্র সংকলনের সময় আকার নির্দিষ্ট করার অনুমতি দেয়

আকার পরিবর্তন করা হচ্ছে

  • arrayএবং unique_ptr<T[]>আকার পরিবর্তন করতে অনুমতি দেবেন না
  • vector না

সংগ্রহস্থল

  • vectorএবং unique_ptr<T[]>অবজেক্টের বাইরে ডেটা সংরক্ষণ করুন (সাধারণত গাদাতে)
  • array সরাসরি অবজেক্টে ডেটা সঞ্চয় করে

অনুলিপি করা হচ্ছে

  • arrayএবং vectorঅনুলিপি অনুমতি দিন
  • unique_ptr<T[]> অনুলিপি অনুমতি দেয় না

সোয়াপ / পদক্ষেপ

  • vectorএবং unique_ptr<T[]>ও (1) সময় swapএবং সরানো ক্রিয়াকলাপ রয়েছে
  • arrayও (এন) সময় swapএবং সরানো ক্রিয়াকলাপ রয়েছে, যেখানে এন অ্যারের উপাদানগুলির সংখ্যা

পয়েন্টার / রেফারেন্স / পুনরুক্তি অবৈধকরণ

  • array পয়েন্টার, রেফারেন্স এবং পুনরুক্তিগুলি অবজেক্টটি লাইভ থাকার সময়েও কখনও অবৈধ হবে না তা নিশ্চিত করে swap()
  • unique_ptr<T[]>কোন পুনরুক্তি আছে; পয়েন্টার এবং রেফারেন্সগুলি কেবল swap()অবজেক্ট থাকে যখন অবজেক্টটি লাইভ থাকে। (অদলবদল করার পরে, পয়েন্টারগুলি আপনি যে অ্যারেটি দিয়েছিলেন সেটিকে নির্দেশ করে, সুতরাং তারা এখনও সেই অর্থে "বৈধ" রয়েছে))
  • vector কোনও পুনঃস্থাপনের ক্ষেত্রে পয়েন্টার, রেফারেন্স এবং পুনরাবৃত্তিকে অবৈধ করতে পারে (এবং কিছু গ্যারান্টি সরবরাহ করে যে পুনর্নির্ধারণ কেবলমাত্র কিছু নির্দিষ্ট ক্রিয়াকলাপেই ঘটতে পারে)।

ধারণা এবং অ্যালগরিদমের সাথে সামঞ্জস্য

  • arrayএবং vectorউভয়ই ধারক
  • unique_ptr<T[]> একটি ধারক নয়

আমাকে স্বীকার করতে হবে, এটি নীতি-ভিত্তিক ডিজাইনের সাথে কিছু রিফ্যাক্টরিংয়ের সুযোগ বলে মনে হচ্ছে।


1
আমি নিশ্চিত নই যে আপনি পয়েন্টার অবৈধতার প্রসঙ্গে আপনার অর্থ কী তা আমি বুঝতে পেরেছি । এটি কি বস্তুগুলিতে পয়েন্টারগুলি নিজেরাই, বা উপাদানগুলির প্রতি নির্দেশকারী? অথবা অন্য কিছু? আপনি কোনও ভেক্টর থেকে পান না এমন অ্যারে থেকে আপনি কী ধরনের গ্যারান্টি পান?
jogojapan

3
মনে করুন যে আপনার কাছে একটি আয়রেটর, একটি পয়েন্টার, বা এর একটি উপাদানের রেফারেন্স রয়েছে vector। তারপরে আপনি এর আকার বা ক্ষমতা বাড়িয়ে vectorতোলেন যা এটি পুনঃস্থাপনে বাধ্য করে। তারপরে সেই পুনরাবৃত্তকারী, পয়েন্টার বা রেফারেন্সটি আর এর উপাদানটির দিকে নির্দেশ করে না vector। এটিই আমরা "অবৈধকরণ" বলতে চাইছি। এই সমস্যাটি ঘটে না array, কারণ "পুনর্বিবেচনা" নেই। প্রকৃতপক্ষে, আমি এটির সাথে কেবল একটি বিশদটি লক্ষ্য করেছি এবং এটি অনুসারে এটি সম্পাদনা করেছি।
ছদ্মনাম

1
ঠিক আছে, একটি অ্যারেতে পুনঃনির্ধারণের ফলাফল হিসাবে বা unique_ptr<T[]>কোনও পুনঃস্থাপনের কারণে অবৈধকরণ হতে পারে না । তবে অবশ্যই, অ্যারে যখন সুযোগের বাইরে চলে যায়, নির্দিষ্ট উপাদানগুলিতে পয়েন্টারগুলি এখনও অবৈধ হবে।
jogojapan

হ্যাঁ, অবজেক্টটি আর লাইভ না থাকলে সমস্ত বেট বন্ধ রয়েছে।
ছদ্মনাম

1
@ রুবেনভব নিশ্চয়ই আপনি পারবেন তবে আপনি লুপগুলির জন্য সরাসরি পরিসীমা-ভিত্তিক ব্যবহার করতে পারবেন না (বলতে পারেন)। ঘটনাচক্রে, অ্যারের উপাদানগুলি সঠিকভাবে ধ্বংস করতে T[]আকারের (বা সমতুল্য তথ্য) কোথাও ঘুরতে হবে operator delete[]। প্রোগ্রামার এর অ্যাক্সেস থাকলে খুব ভাল লাগবে be
ছদ্মনাম

73

আপনি unique_ptrযদি ব্যবহার করতে পারেন তার একটি কারণ হ'ল যদি আপনি অ্যারের মান-আরম্ভ করার জন্য রানটাইম ব্যয়টি দিতে না চান ।

std::vector<char> vec(1000000); // allocates AND value-initializes 1000000 chars

std::unique_ptr<char[]> p(new char[1000000]); // allocates storage for 1000000 chars

std::vectorকন্সট্রাকটর এবং std::vector::resize()ভ্যালু আরম্ভ হবে T- কিন্তু newযে যদি করবে না Tএকটি শুঁটি হয়।

সি ++ 11 এবং স্টাড :: ভেক্টর কনস্ট্রাক্টর-এ মান-সূচনাযুক্ত অবজেক্টগুলি দেখুন

নোট যে vector::reserveএখানে বিকল্প নয়: স্টাড :: ভেক্টর :: সংরক্ষণের পরে কাঁচা পয়েন্টার অ্যাক্সেস করা কি নিরাপদ?

এটা তোলে একই কারণে একটি সি প্রোগ্রামার চয়ন করতে পারে এর mallocবেশি calloc


তবে এই কারণটিই একমাত্র সমাধান নয়
রুসলান

@ রুস্লান লিঙ্কযুক্ত সমাধানে গতিশীল অ্যারের উপাদানগুলি এখনও মান-আরম্ভ হয়, তবে মান সূচনা কিছুই করে না। আমি সম্মত হব যে একটি অপ্টিমাইজার যে এটি বুঝতে ব্যর্থ হয় যে কোনও কোড দ্বারা ১০০০০০০০ বার করা সম্ভব নয় তা কোনও ডাইম মূল্য নয়, তবে কেউ এই অপ্টিমাইজেশানের উপর নির্ভর করতে নাও পছন্দ করতে পারেন।
মার্ক ভ্যান লিউউইন

তবুও আরেকটি সম্ভাবনা হ'ল std::vectorএকটি কাস্টম বরাদ্দকারীকে সরবরাহ করা যা এমন ধরণের যা নির্মাণের বিষয়গুলি std::is_trivially_default_constructibleএবং যা বস্তুগুলির ধ্বংসকে এড়িয়ে চলে তা এড়িয়ে চলে std::is_trivially_destructible, যদিও এটি কঠোরভাবে সি ++ মানকে লঙ্ঘন করে (যেহেতু এই ধরণের ধরণের ডিফল্ট সূচনা হয় না)।
ওয়াল্টার

এছাড়াও std::unique_ptrঅনেক কোনো আবদ্ধ পরীক্ষণ বিপরীত উপলব্ধ করা হয় না std::vectorবাস্তবায়নের।
ডায়াপির

30

একটি std::vectorচারপাশে অনুলিপি করা যেতে পারে, এবং unique_ptr<int[]>অ্যারের অনন্য মালিকানা প্রকাশ করার অনুমতি দেয়। std::arrayঅন্যদিকে, সংকলন সময়ে আকার নির্ধারণ করা দরকার যা কিছু পরিস্থিতিতে অসম্ভব হয়ে উঠতে পারে।


2
কিছু কিছু আশেপাশে অনুলিপি করা যেতে পারে তার অর্থ এটি হওয়া উচিত নয়।
নিকল বলাস

4
@ নিকোলবোলাস: আমি বুঝতে পারি না। যে কেউ এর unique_ptrপরিবর্তে কেন ব্যবহার করবে একই কারণে এটি প্রতিরোধ করতে চাইতে পারে shared_ptr। আমি কিছু অনুপস্থিত করছি?
অ্যান্ডি প্রোল

4
unique_ptrদুর্ঘটনাজনিত অপব্যবহার রোধ করার চেয়ে আরও বেশি কিছু করে। এটি এর চেয়ে ছোট এবং ওভারহেডও shared_ptr। মূল বিষয়টি এমন যে, "অপব্যবহার" রোধ করে এমন একটি ক্লাসে শব্দার্থক শব্দ রাখা ভাল, তবে এটি কোনও নির্দিষ্ট ধরণের ব্যবহারের একমাত্র কারণ নয়। আর vectorচেয়ে একটি অ্যারের সঞ্চয়স্থান হিসাবে অনেক বেশী দরকারী unique_ptr<T[]>, আসলে এটি একটি আছে যা ছাড়া অন্য কোন কারণে যদি আকার
নিকল বলাস

3
আমি ভেবেছিলাম আমি বিষয়টি পরিষ্কার করে দিয়েছি: এর চেয়ে নির্দিষ্ট কারণ ব্যবহারের অন্যান্য কারণও রয়েছে । ঠিক যেখানে "আপনি এটি অনুলিপি করতে পারবেন না" বলার পরিবর্তে যেখানে সম্ভব সেখানে vectorবেশি পছন্দ করার কারণ রয়েছে unique_ptr<T[]>এবং unique_ptr<T[]>যখন আপনি অনুলিপিগুলি চান না তখন বেছে নিন pick কাউকে ভুল কাজ করা থেকে বিরত করা ক্লাস বাছাইয়ের সবচেয়ে গুরুত্বপূর্ণ কারণ নয়।
নিকল বলাস

8
std::vectorএর চেয়ে বেশি ওভারহেড রয়েছে std::unique_ptr- এতে ~ 1 এর পরিবর্তে ~ 3 পয়েন্টার ব্যবহার করা হয়। std::unique_ptrঅনুলিপি নির্মাণকে অবরুদ্ধ করে তবে সরানো নির্মাণকে সক্ষম করে, যা শব্দার্থকভাবে আপনি কাজ করছেন এমন ডেটা কেবল স্থানান্তরিত হতে পারে তবে অনুলিপি করা যায় না, ডেটাযুক্ত classতথ্যকে সংক্রামিত করে । বৈধ নয় এমন ডেটাতে অপারেশন করা আপনার ধারক শ্রেণিকে আরও খারাপ করে তোলে এবং "কেবল এটি ব্যবহার করবেন না" সমস্ত পাপ ধুয়ে দেয় না। নিজের প্রতিটি দৃষ্টান্ত std::vectorএমন একটি ক্লাসে স্থাপন করা যেখানে আপনি ম্যানুয়ালি অক্ষম হয়ে পড়ছেন moveতা মাথা ব্যথা is std::unique_ptr<std::array>একটি আছে size
ইয়াক্ক - অ্যাডাম নেভ্রামুমন্ট

22

স্কট মায়ার্স এটিকে কার্যকর আধুনিক সি ++ তে বলতে পারেন

অস্তিত্ব std::unique_ptrজন্য অ্যারে, আপনি শুধুমাত্র বুদ্ধিজীবী সুদ হওয়া উচিত কারণ std::array, std::vector, std::stringকাঁচা অ্যারে চেয়ে ভাল ডাটা স্ট্রাকচার পছন্দ কার্যত সবসময়। আমি std::unique_ptr<T[]>যখন সি-এর মতো এপিআই ব্যবহার করি যা আপনি নিজের মালিকানা অনুমান করেন এমন একটি কাঁচা পয়েন্টার ফেরত দেয় এমন একমাত্র পরিস্থিতি সম্পর্কে আমি কল্পনা করতে পারি About

আমি মনে করি যে চার্লস সালভিয়ার উত্তরটি প্রাসঙ্গিক যদিও: std::unique_ptr<T[]>খালি অ্যারে শুরু করার একমাত্র উপায় যার আকার সঙ্কলনের সময় জানা যায় না known স্কট মায়ার্স ব্যবহারের জন্য এই অনুপ্রেরণা সম্পর্কে কী বলতে হবে std::unique_ptr<T[]>?


4
মনে হচ্ছে তিনি কেবল কয়েকটি ব্যবহারের ক্ষেত্রে কল্পনা করেন নি, যথা একটি বাফার যার আকার স্থির কিন্তু সংকলনের সময় অজানা, এবং / বা এমন একটি বাফার যার জন্য আমরা অনুলিপিগুলিকে অনুমতি দিই না। এটি vector স্ট্যাকওভারফ্লো . com/ a/ 24852984/2436175 এ পছন্দ করার সম্ভাব্য কারণ হিসাবে দক্ষতাও রয়েছে ।
আন্তোনিও

17

পক্ষান্তরে std::vectorএবং std::array, std::unique_ptrএকটি NULL পয়েন্টার অধিকারী হতে পারেন।
সি এপিআইগুলির সাথে কাজ করার সময় এটি কার্যকর হয় যা কোনও অ্যারে বা NULL আশা করে:

void legacy_func(const int *array_or_null);

void some_func() {    
    std::unique_ptr<int[]> ptr;
    if (some_condition) {
        ptr.reset(new int[10]);
    }

    legacy_func(ptr.get());
}

10

আমি unique_ptr<char[]>একটি গেম ইঞ্জিনে ব্যবহৃত পূর্বনির্ধারিত মেমরি পুলগুলি প্রয়োগ করতে ব্যবহার করেছি । ধারণাটি হ'ল সংঘর্ষের অনুরোধের ফলাফলগুলি এবং প্রতিটি ফ্রেমের জন্য নিখরচায় / ফ্রি মেমরি ছাড়াই কণা পদার্থবিজ্ঞানের মতো অন্যান্য স্টাফগুলির জন্য গতিশীল বরাদ্দের পরিবর্তে ব্যবহৃত পূর্বরূপযুক্ত মেমরি পুল সরবরাহ করা। এটি এই জাতীয় দৃশ্যের জন্য বেশ সুবিধাজনক যেখানে আপনার সীমিত জীবনের সময় (সাধারণত এক, ২ বা 3 ফ্রেম) সহ বস্তু বরাদ্দ করতে মেমরি পুলগুলি প্রয়োজন যাগুলির জন্য বিন্যাস যুক্তি (কেবলমাত্র মেমরি বিলোপ) প্রয়োজন হয় না।


9

কিছু উইন্ডোজ উইন 32 এপিআই কলগুলিতে একটি সাধারণ প্যাটার্ন পাওয়া যায় , যেখানে ব্যবহারটি কার্যকর হতে std::unique_ptr<T[]>পারে, উদাহরণস্বরূপ, যখন আপনি কিছু জানেন না যে কোনও উইন 32 এপিআই কল করার সময় আউটপুট বাফারটি কত বড় হওয়া উচিত (যা কিছু তথ্য ভিতরে লিখবে) যে বাফার):

// Buffer dynamically allocated by the caller, and filled by some Win32 API function.
// (Allocation will be made inside the 'while' loop below.)
std::unique_ptr<BYTE[]> buffer;

// Buffer length, in bytes.
// Initialize with some initial length that you expect to succeed at the first API call.
UINT32 bufferLength = /* ... */;

LONG returnCode = ERROR_INSUFFICIENT_BUFFER;
while (returnCode == ERROR_INSUFFICIENT_BUFFER)
{
    // Allocate buffer of specified length
    buffer.reset( BYTE[bufferLength] );
    //        
    // Or, in C++14, could use make_unique() instead, e.g.
    //
    // buffer = std::make_unique<BYTE[]>(bufferLength);
    //

    //
    // Call some Win32 API.
    //
    // If the size of the buffer (stored in 'bufferLength') is not big enough,
    // the API will return ERROR_INSUFFICIENT_BUFFER, and the required size
    // in the [in, out] parameter 'bufferLength'.
    // In that case, there will be another try in the next loop iteration
    // (with the allocation of a bigger buffer).
    //
    // Else, we'll exit the while loop body, and there will be either a failure
    // different from ERROR_INSUFFICIENT_BUFFER, or the call will be successful
    // and the required information will be available in the buffer.
    //
    returnCode = ::SomeApiCall(inParam1, inParam2, inParam3, 
                               &bufferLength, // size of output buffer
                               buffer.get(),  // output buffer pointer
                               &outParam1, &outParam2);
}

if (Failed(returnCode))
{
    // Handle failure, or throw exception, etc.
    ...
}

// All right!
// Do some processing with the returned information...
...

আপনি কেবল std::vector<char>এই ক্ষেত্রে ব্যবহার করতে পারেন ।
আর্থার টাক্কা

@ আর্থার ট্যাক্কা - ... আপনি যদি নিজের বাফারের প্রতিটি চরিত্রকে এক-এক-এক করে আরম্ভ করার সংকলকটি কিছু মনে করেন না।
টেড

9

আমি এমন একটি মামলার মুখোমুখি হয়েছি যেখানে আমাকে ব্যবহার করতে std::unique_ptr<bool[]>হয়েছিল, যা এইচডিএফ 5 লাইব্রেরিতে ছিল (দক্ষ বাইনারি ডেটা সঞ্চয় করার জন্য একটি গ্রন্থাগার, বিজ্ঞানে প্রচুর ব্যবহৃত হয়েছিল)। কিছু সংকলক (আমার ক্ষেত্রে ভিজ্যুয়াল স্টুডিও 2015) সংকোচনের ব্যবস্থা করেstd::vector<bool> (প্রতিটি বাইটে 8 টি বুল ব্যবহার করে), যা এইচডিএফ 5 এর মতো কোনও কিছুর জন্য বিপর্যয়, যা সেই সংকোচনের বিষয়ে চিন্তা করে না। সহ std::vector<bool>, এইচডিএফ 5 শেষ পর্যন্ত সেই সংকোচনের কারণে আবর্জনা পড়ছিল।

অনুমান করুন যে উদ্ধারকাজের জন্য সেখানে কে ছিলেন, এমন কোনও ক্ষেত্রে যেখানে std::vectorকাজ হয়নি এবং আমার পরিষ্কারভাবে একটি গতিশীল অ্যারে বরাদ্দ করা দরকার? :-)


9

সংক্ষেপে: এটি এখন পর্যন্ত সবচেয়ে স্মৃতি-দক্ষ।

std::stringপয়েন্টার, একটি দৈর্ঘ্য এবং একটি "শর্ট-স্ট্রিং-অপ্টিমাইজেশন" বাফার নিয়ে আসে। তবে আমার পরিস্থিতি হ'ল আমাকে এমন স্ট্রিং সংরক্ষণ করতে হবে যা প্রায় সর্বদা শূন্য থাকে, এমন কাঠামোতে আমার কয়েক হাজার রয়েছে have সি তে, আমি কেবল ব্যবহার করব char *এবং এটি বেশিরভাগ সময় শূন্য থাকবে। যা সি ++ এর জন্যও কাজ করে, এর বাদশাহর char *কোনও ডেস্ট্রাক্টর নেই এবং সে নিজেকে মুছে ফেলতে জানে না। বিপরীতে, একটি ক্ষেত্রের std::unique_ptr<char[]>বাইরে গেলে একটি নিজেকে মুছে ফেলবে। একটি খালি std::string32 বাইট নেয়, কিন্তু একটি খালি std::unique_ptr<char[]>8 বাইট নেয়, এটি হ'ল এটির পয়েন্টারের আকার।

সবচেয়ে বড় ক্ষতিটি হ'ল, যতবারই আমি স্ট্রিংয়ের দৈর্ঘ্য জানতে চাইছি, আমাকে strlenএটির কল করতে হবে।


3

লোকেদের ভাবার জন্য আপনাকে জিপিইউতে সিইডিডিএ প্রোগ্রামিংয়ের ক্ষেত্রে আমার "এর vectorপরিবর্তে " ব্যবহার করতে হবে " unique_ptrযখন আপনি ডিভাইসে মেমরি বরাদ্দ করেন আপনাকে অবশ্যই পয়েন্টার অ্যারে (সহ cudaMalloc) যেতে হবে । তারপরে, হোস্টে এই ডেটাটি পুনরুদ্ধার করার সময়, আপনাকে অবশ্যই পয়েন্টারের জন্য আবার যেতে হবে এবং unique_ptrপয়েন্টারটি সহজেই পরিচালনা করতে ভাল fine রূপান্তর double*করার অতিরিক্ত ব্যয় vector<double>অপ্রয়োজনীয় এবং পারফফুল লোকসানের দিকে নিয়ে যায়।


3

অনুমতি এবং ব্যবহারের জন্য একটি অতিরিক্ত কারণ std::unique_ptr<T[]>, যা এখনও পর্যন্ত প্রতিক্রিয়াগুলিতে উল্লেখ করা হয়নি: এটি আপনাকে অ্যারে উপাদান ধরণের ফরোয়ার্ড-ডিক্লেয়ার করতে দেয়।

আপনি যখন #includeশিরোনামগুলিতে শৃঙ্খলাবদ্ধ বিবৃতিগুলি ছোট করতে চান (বিল্ড পারফরম্যান্স অনুকূল করতে) এটি কার্যকর হয় This

এই ক্ষেত্রে -

myclass.h:

class ALargeAndComplicatedClassWithLotsOfDependencies;

class MyClass {
   ...
private:
   std::unique_ptr<ALargeAndComplicatedClassWithLotsOfDependencies[]> m_InternalArray;
};

myclass.cpp:

#include "myclass.h"
#include "ALargeAndComplicatedClassWithLotsOfDependencies.h"

// MyClass implementation goes here

উপরের কোড কাঠামোর সাহায্যে, যে কেউ অভ্যন্তরীণ বাস্তবায়ন নির্ভরতাগুলি অন্তর্ভুক্ত না করেই #include "myclass.h"এবং ব্যবহার MyClassকরতে পারে MyClass::m_InternalArray

m_InternalArrayপরিবর্তে যদি যথাক্রমে a std::array<ALargeAndComplicatedClassWithLotsOfDependencies>, বা a হিসাবে ঘোষণা করা std::vector<...>হয় - ফলাফলটি একটি অসম্পূর্ণ প্রকারের চেষ্টা করার চেষ্টা করা হবে যা একটি সংকলন-সময় ত্রুটি।


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

3

আমি দৃ strongly়ভাবে গ্রহণযোগ্য উত্তরের আত্মার সাথে একমত হতে পারি না। "শেষ অবলম্বনের একটি সরঞ্জাম"? অনেক দূরে!

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

সুতরাং যখন কারোর জন্য অ্যারের প্রয়োজন হয়, নিম্নলিখিত প্রশ্নের উত্তরগুলি তার আচরণটি নির্দিষ্ট করে: ১. এর আকার ক) রানটাইম এ গতিশীল, বা খ) স্থির, তবে কেবল রানটাইমেই পরিচিত, বা গ) স্থির এবং সংকলনের সময় পরিচিত? 2. অ্যারে স্ট্যাকের উপর বরাদ্দ করা যেতে পারে বা না?

এবং উত্তরের উপর ভিত্তি করে, এটি আমি এ জাতীয় অ্যারের জন্য সেরা ডেটা কাঠামো হিসাবে দেখছি:

       Dynamic     |   Runtime static   |         Static
Stack std::vector      unique_ptr<T[]>          std::array
Heap  std::vector      unique_ptr<T[]>     unique_ptr<std::array>

হ্যাঁ, আমি মনে করি unique_ptr<std::array>এটিও বিবেচনা করা উচিত, এবং উভয়ই সর্বশেষ সমাধানের একটি সরঞ্জাম নয়। আপনার অ্যালগরিদমের সাথে কী সেরা ফিট করে তা ভাবুন।

এগুলি সমস্ত ডেটা অ্যারে ( vector.data()/ array.data()/ uniquePtr.get()) এর কাঁচা পয়েন্টারের মাধ্যমে প্লেইন সি এপিআইগুলির সাথে সামঞ্জস্যপূর্ণ ।

পিএস উপরোক্ত বিবেচনাগুলি বাদে মালিকানার একটিও রয়েছে: std::arrayএবং std::vectorমান শব্দার্থক (মান দ্বারা অনুলিপি করা এবং পাস করার জন্য স্থানীয় সমর্থন রয়েছে) রয়েছে, তবে unique_ptr<T[]>কেবল স্থানান্তরিত হতে পারে (একক মালিকানা প্রয়োগ করে)। হয় বিভিন্ন পরিস্থিতিতে কার্যকর হতে পারে। বিপরীতে, সাধারণ স্ট্যাটিক অ্যারে ( int[N]) এবং সরল গতিশীল অ্যারে ( new int[10]) প্রস্তাব দেয় না এবং তাই সম্ভব হলে এড়ানো উচিত - যা বেশিরভাগ ক্ষেত্রেই সম্ভব হওয়া উচিত। যদি এটি পর্যাপ্ত পরিমাণে না ছিল, সরল গতিশীল অ্যারেগুলি তাদের আকারটি জিজ্ঞাসা করার কোনও উপায়ও দেয় না - মেমরির দুর্নীতি এবং সুরক্ষা গর্তের জন্য অতিরিক্ত সুযোগ।


2

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

unique_ptr<byte[]> data = get_some_data();

threadpool->post_work([](void* param) { do_a_thing(unique_ptr<byte[]>((byte*)param)); },
                      data.release());

আমরা সকলেই চাই আমাদের জন্য জিনিসগুলি সুন্দর হোক। সি ++ অন্যান্য বারের জন্য।


2

unique_ptr<char[]>আপনি যেখানে সি এর পারফরম্যান্স এবং সি ++ এর সুবিধার্থ চান সেখানে ব্যবহার করা যেতে পারে। আপনার কয়েক লক্ষ স্ট্রিং (ঠিক আছে, যদি আপনি এখনও বিশ্বাস না করেন তবে বিলিয়ন) এর স্ট্রিংয়ের কথা বিবেচনা করুন। এগুলির প্রত্যেককে পৃথক stringবা vector<char>বস্তুতে সংরক্ষণ করা মেমোরি (হিপ) পরিচালনার রুটিনগুলির জন্য একটি বিপর্যয় be বিশেষত আপনার যদি বিভিন্ন স্ট্রিং বরাদ্দ করতে এবং মুছে ফেলার প্রয়োজন হয় times

তবে, আপনি বহু স্ট্রিং সংরক্ষণের জন্য একটি একক বাফার বরাদ্দ করতে পারেন। আপনি char* buffer = (char*)malloc(total_size);সুস্পষ্ট কারণে পছন্দ করবেন না (যদি স্পষ্ট না হয় তবে "কেন স্মার্ট পিটিআর ব্যবহার করুন" অনুসন্ধান করুন)। আপনি বরং পছন্দ করেনunique_ptr<char[]> buffer(new char[total_size]);

উপমা অনুসারে, একই কর্মক্ষমতা এবং সুবিধার বিবেচনাগুলি অ- charডেটাতে প্রয়োগ হয় (লক্ষ লক্ষ ভেক্টর / ম্যাট্রিক / বস্তু বিবেচনা করুন)।


একটি বড় সব মধ্যে রাখা না vector<char>? উত্তর, আমি অনুমান, কারণ তারা হবে শূন্য ইনিশিয়ালাইজ যখন আপনি বাফার তৈরি করেন, যেহেতু তারা যদি আপনি ব্যবহার হবে না unique_ptr<char[]>। তবে এই উত্তরটি আপনার উত্তর থেকে অনুপস্থিত।
আর্থার টাক্কা

2
  • বাইনারি-সামঞ্জস্যের কারণে আপনার পয়েন্টার কেবলমাত্র আপনার কাঠামোর প্রয়োজন।
  • আপনাকে এমন একটি API এর সাথে ইন্টারফেস করতে হবে যা বরাদ্দ হওয়া মেমরিটি ফেরত দেয় new[]
  • আপনার ফার্ম বা প্রকল্পের সাধারণ নিয়ম রয়েছে ব্যবহারের বিরুদ্ধে std::vector, উদাহরণস্বরূপ, অযত্নে প্রোগ্রামারদের দুর্ঘটনাক্রমে অনুলিপিগুলি প্রবর্তন থেকে বিরত রাখতে
  • অযত্নে প্রোগ্রামারদের দুর্ঘটনাক্রমে এই দৃষ্টান্তে অনুলিপিগুলি প্রবর্তন করা থেকে বিরত রাখতে চান।

একটি সাধারণ নিয়ম রয়েছে যে সি ++ পাত্রে পয়েন্টারগুলির সাথে আপনার নিজের-রোলিংয়ের চেয়ে বেশি পছন্দ করা উচিত। এটি একটি সাধারণ নিয়ম; এটি ব্যতিক্রম আছে। আরো আছে; এগুলি কেবল উদাহরণ।


0

যদি আপনার অবজেক্টগুলির একটি গতিশীল অ্যারে প্রয়োজন হয় যা অনুলিপি-গঠনযোগ্য নয়, তবে অ্যারেতে একটি স্মার্ট পয়েন্টার হ'ল উপায়। উদাহরণস্বরূপ, যদি আপনার পরমাণুগুলির একটি অ্যারের প্রয়োজন হয়।

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