স্ট্যান্ড :: মেক_উইনিক এবং স্টাডি :: অনন্য_পিটারের সাথে নতুন সহ পার্থক্য


130

এর std::make_uniqueমতো কোনও দক্ষতার বেনিফিট রয়েছে std::make_shared?

ম্যানুয়ালি নির্মাণের তুলনায় std::unique_ptr:

std::make_unique<int>(1);         // vs
std::unique_ptr<int>(new int(1));

make_sharedদীর্ঘ হাতের কোডটি লেখার ক্ষেত্রে কি কোনও দক্ষতা রয়েছে?
এড নিরাময়

9
@ এডহেল এটি হতে পারে, কারণ make_sharedকোনও একক বরাদ্দে অবজেক্টের জন্য স্থান এবং নিয়ন্ত্রণ ব্লকের জন্য স্থান উভয়ই বরাদ্দ করতে পারে । এর ব্যয়টি হ'ল এই অবজেক্টটি নিয়ন্ত্রণ ব্লক থেকে আলাদা করে বিলোপ করা যায় না, তাই আপনি যদি weak_ptrঅনেক বেশি ব্যবহার করেন তবে আপনি আরও মেমরি ব্যবহার করে শেষ করতে পারেন।
bames53

সম্ভবত এটি একটি ভাল সূচনা পয়েন্ট stackoverflow.com/questions/9302296/…
এড হিল

উত্তর:


140

পিছনে অনুপ্রেরণা make_uniqueমূলত দ্বিগুণ:

  • make_uniqueঅস্থায়ীতা তৈরির জন্য নিরাপদ, অন্যদিকে স্পষ্টভাবে newআপনাকে বেনামে টেম্পোরারি না ব্যবহারের নিয়মটি মনে রাখতে হবে।

    foo(make_unique<T>(), make_unique<U>()); // exception safe
    
    foo(unique_ptr<T>(new T()), unique_ptr<U>(new U())); // unsafe*
  • make_uniqueশেষ অবধি সংযোজনটির অর্থ আমরা লোকদের বলতে পারি যে আপনি যখন " তৈরি করেন " ব্যতীত newআগের নিয়মের পরিবর্তে "কখনই" ব্যবহার না করার জন্য 'কখনই' ব্যবহার করতে বলি ।newunique_ptr

তৃতীয় কারণও রয়েছে:

  • make_uniqueঅপ্রয়োজনীয় ধরণের ব্যবহারের প্রয়োজন হয় না। unique_ptr<T>(new T())->make_unique<T>()

রানটাইম দক্ষতা উন্নত করার কারণগুলির মধ্যে কোনওটিই make_shared(সম্ভাব্য উচ্চতর শিখর মেমরির ব্যবহার ব্যয় করে দ্বিতীয় বরাদ্দ এড়ানো কারণে) ব্যবহার করে না।

* এটি প্রত্যাশিত যে সি ++ 17 এর মধ্যে একটি বিধি পরিবর্তন অন্তর্ভুক্ত হবে যার অর্থ এটি আর নিরাপদ নয়। সি ++ কমিটির কাগজপত্রগুলি P0400R0 এবং P0145R3 দেখুন


এটি বলার চেয়ে আরও অর্থবোধ করে std::unique_ptrএবং std::shared_ptrআমরা কেন লোকদের "কখনই ব্যবহার না করে" বলতে পারি new
টিমোথি শিল্ডস

2
@ টিমোথিশিল্ডস হ্যাঁ, এটাই আমার অর্থ। এটি কেবলমাত্র আমাদের C ++ 11 make_sharedmake_uniqueছিল এবং এর আগে চূড়ান্ত অংশটি ছিল অনুপস্থিত।
bames53

1
কোনওভাবেই আপনি সংক্ষিপ্তভাবে উল্লেখ করতে পারেন, বা এর সাথে লিঙ্ক, নামবিহীন অস্থায়ী ব্যবহার না করার কারণ?
ড্যান নিসেনবাউম

14
আসলে, থেকে stackoverflow.com/a/19472607/368896 , আমি এটা ... যেটা উত্তর থেকে, বিবেচনা নিম্নলিখিত ফাংশন কল পেয়েছেন f: f(unique_ptr<T>(new T), function_that_can_throw());-: উত্তর উদ্ধৃত করা (অনুক্রমে) কম্পাইলার কল করার অনুমতি দেওয়া হয়: new T, function_that_can_throw(), unique_ptr<T>(...)। স্পষ্টত যদি function_that_can_throwআসলে ছুড়ে ফেলে তবে আপনি ফুটো হন। make_uniqueএই ক্ষেত্রে প্রতিরোধ করে। সুতরাং, আমার প্রশ্নের উত্তর দেওয়া হয়েছে।
ড্যান নিসেনবাউম

3
আমাকে একবার স্টাড :: ইউনিক_পিটার <টি> (নতুন টি ()) ব্যবহার করতে হয়েছিল তার কারণ ছিল টির নির্মাণকারী ব্যক্তিগত। এমনকি স্ট্যান্ড :: মেক_উনিকের কাছে কলটি টি শ্রেণির পাবলিক কারখানার পদ্ধতিতে থাকলেও এটি সংকলন করেনি কারণ স্ট্যান্ড :: মেক_উনিকের অন্তর্নিহিত পদ্ধতিগুলির মধ্যে একটি বেসরকারী নির্মাণকারী অ্যাক্সেস করতে পারেনি। আমি সেই পদ্ধতিটিকে বন্ধু করতে চাইনি কারণ আমি স্ট্যান্ড :: মেক_উনিক বাস্তবায়নের উপর নির্ভর করতে চাই না। সুতরাং একমাত্র সমাধান ছিল, আমার ক্লাস টিয়ের ফ্যাক্টরি পদ্ধতিতে নতুন কল করা, এবং তারপরে এটি একটি স্টাড :: অনন্য_আপনার <টি> এ মোড়ানো।
প্যাট্রিক

14

std::make_uniqueএবং std::make_sharedদুটি কারণে রয়েছে:

  1. যাতে আপনাকে স্পষ্টভাবে টেম্পলেট ধরণের আর্গুমেন্টগুলি তালিকাভুক্ত করতে না হয়।
  2. ব্যবহার std::unique_ptrবা std::shared_ptrনির্মাণকারীদের উপর অতিরিক্ত ব্যতিক্রম সুরক্ষা । ( এখানে নোটস বিভাগটি দেখুন ।)

এটি রানটাইম দক্ষতা সম্পর্কে আসলেই নয়। নিয়ন্ত্রণ ব্লক এবং Tসমস্ত একবারে বরাদ্দ দেওয়া সম্পর্কে কিছুটা রয়েছে তবে আমি মনে করি যে এটি বেশি বোনাস এবং এই ফাংশনগুলির অস্তিত্বের জন্য একটি প্রেরণা কম।


ব্যতিক্রম-সুরক্ষার জন্য তারা সেখানে রয়েছে।
0x499602D2

@ 0x499602D2 এবং এটি, ভাল সংযোজন। এই পৃষ্ঠাটি সম্পর্কে আলোচনা।
তীমথিয় শিল্ডস

ভবিষ্যতের পাঠকদের জন্য, সি ++ 17 ফাংশন আর্গুমেন্টগুলি ইন্টারলেভ করার অনুমতি দেয় না যাতে ব্যতিক্রম-সুরক্ষার পক্ষে যুক্তিটি আর ধরে না। দুটি সমান্তরাল জন্য মেমরি বরাদ্দ std::make_sharedনিশ্চিত করা হবে যে অন্য মেমরি বরাদ্দ হওয়ার আগে তাদের মধ্যে অন্তত একটি স্মার্ট পয়েন্টারে আবৃত হয়ে যায়, সুতরাং কোনও ফাঁস হয় না।
ম্যাথবুনি

7

আপনি std::unique_ptr(new A())বা std::shared_ptr(new A())সরাসরি পরিবর্তে ব্যবহার করতে হবে এমন একটি কারণ বর্তমান সুযোগের বাইরে std::make_*()শ্রেণীর Aনির্মাতাকে অ্যাক্সেস করতে ব্যর্থ হচ্ছে ।


0

ফাংশন কল বিবেচনা করুন

void function(std::unique_ptr<A>(new A()), std::unique_ptr<B>(new B())) { ... }

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

void function(std::make_unique<A>(), std::make_unique<B>()) { ... }

এখানে বক্তব্যটি হ'ল std::make_unique<A>এবং std::make_unique<B>এখন অস্থায়ী অবজেক্ট এবং অস্থায়ী বস্তুর সাফাই সঠিকভাবে সি ++ স্ট্যান্ডার্ডে নির্দিষ্ট করা হয়েছে: তাদের ধ্বংসকারীদের ট্রিগার করা হবে এবং মেমরিটি মুক্ত করা হবে। সুতরাং যদি আপনি পারেন তবে সর্বদা std::make_uniqueএবং ব্যবহার করে অবজেক্টগুলি বরাদ্দ করতে পছন্দ করুন std::make_shared

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