সি ++ 17 এ কেন স্ট্যান্ড :: মেক_উনিক ব্যবহার করবেন?


96

আমি যতদূর বুঝতে পেরেছি, সি ++ 14 চালু করেছে std::make_uniqueকারণ, প্যারামিটারের মূল্যায়ন আদেশ নির্দিষ্ট না করার ফলে এটি অনিরাপদ ছিল:

f(std::unique_ptr<MyClass>(new MyClass(param)), g()); // Syntax A

(ব্যাখ্যা: যদি মূল্যায়ন প্রথমে কাঁচা পয়েন্টারটির জন্য মেমরির বরাদ্দ দেয়, তবে কল করার পরে g()কোনও ব্যতিক্রম std::unique_ptrনির্মাণের আগে নিক্ষেপ করা হয় , তবে স্মৃতিটি ফাঁস হয়))

কল std::make_uniqueকরা কল অর্ডারকে সীমাবদ্ধ করার উপায় ছিল, সুতরাং জিনিসগুলি নিরাপদ করে তুলেছিল:

f(std::make_unique<MyClass>(param), g());             // Syntax B

তারপর থেকে, সি ++ 17 মূল্যায়ন অর্ডার বিষয়টিকে ব্যাখ্যা করেছে, খুব সিনট্যাক্স একটি নিরাপদ করা, তাই এখানে আমার প্রশ্ন হল: এখনও ব্যবহার করার জন্য একটি কারণ নেই std::make_uniqueওভারstd::unique_ptr সি ++ 17 কন্সট্রাকটর কইলাম? আপনি কিছু উদাহরণ দিতে পারেন?

এখন পর্যন্ত, আমি কল্পনা করতে পারি তার একমাত্র কারণ এটি MyClassকেবল একবার টাইপ করতে দেয় (ধরে নিলে আপনার বহুবর্ষের উপর নির্ভর করার দরকার নেই std::unique_ptr<Base>(new Derived(param)))। তবে এটি বেশ দুর্বল কারণে বলে মনে হচ্ছে, বিশেষত যখন std::make_uniqueকনস্ট্রাক্টর যখন কোনও মুছে ফেলা নির্দিষ্ট করতে দেয় std::unique_ptrনা।

এবং কেবল পরিষ্কারভাবেই বলা যায়, আমি std::make_uniqueস্ট্যান্ডার্ড লাইব্রেরি থেকে সরিয়ে নেওয়ার পক্ষে সমর্থন দিচ্ছি না (এটি অন্তত পশ্চাদপদ সামঞ্জস্যের জন্য উপলব্ধি করে), তবে ভাবছেন যে এখনও এমন পরিস্থিতি রয়েছে যেখানে এটির চেয়ে দৃ strongly়ভাবে অগ্রাধিকার দেওয়া হয়েছে?std::unique_ptr


4
তবে এটি বেশ দুর্বল কারণে বলে মনে হচ্ছে -> এটি কেন একটি দুর্বল কারণ? এটি কার্যকরভাবে প্রকারের কোড নকলকে হ্রাস করে। মুছে ফেলার ক্ষেত্রে, আপনি ব্যবহার করার সময় কতবার কাস্টম মুছুন ব্যবহার করছেন std::unique_ptr? এটি বিরুদ্ধে কোন যুক্তি নয়make_unique
llllllllll

4
আমি বলছি এটি একটি দুর্বল কারণ কারণ যদি std::make_uniqueপ্রথম স্থানে না থাকে তবে আমি এটি এসটিএলে যুক্ত করার পক্ষে যথেষ্ট কারণ বলে মনে করি না, বিশেষত যখন এটি একটি সিনট্যাক্স যা কনস্ট্রাক্টর ব্যবহারের চেয়ে কম প্রকাশ করে, বেশি না
চিরদিনের

4
আপনার যদি মেক_উনিক ব্যবহার করে সি ++ 14 এ তৈরি করা একটি প্রোগ্রাম থাকে তবে আপনি চান না যে ফাংশনটি stl থেকে সরানো হোক। অথবা আপনি যদি এটি পিছনে সামঞ্জস্যপূর্ণ হতে চান।
সার্জ করুন

4
@ সার্জ এটি একটি ভাল বিষয়, তবে এটি আমার প্রশ্নের উদ্দেশ্য ছাড়াও কিছুটা bit আমি এটি আরও পরিষ্কার করার জন্য একটি সম্পাদনা করব
চিরন্তন

4
@ শাশ্বত দয়া করে এসটিএল হিসাবে সি ++ স্ট্যান্ডার্ড লাইব্রেরিটি উল্লেখ করা বন্ধ করুন কারণ এটি ভুল এবং বিভ্রান্তি সৃষ্টি করে। দেখুন stackoverflow.com/questions/5205491/...
Marandil

উত্তর:


76

আপনি ঠিক বলেছেন যে মূল কারণটি সরানো হয়েছিল। এখনও নতুন নির্দেশিকাগুলি ব্যবহার করবেন না এবং এটি টাইপিংয়ের কারণগুলি কম (এ ধরণের পুনরাবৃত্তি বা শব্দটি ব্যবহার করতে হবে না new)। স্বীকারোক্তিজনকভাবে সেগুলি দৃ strong় যুক্তি নয় তবে আমি আমার কোডটিতে না দেখে সত্যিই পছন্দ newকরি।

ধারাবাহিকতা সম্পর্কে ভুলবেন না আপনি একেবারে ব্যবহার করা উচিত make_sharedতাই ব্যবহার make_uniqueপ্রাকৃতিক এবং প্যাটার্ন ফিট করে। এরপরে এটি পরিবর্তন std::make_unique<MyClass>(param)করতে তুচ্ছ std::make_shared<MyClass>(param)(বা বিপরীতে) যেখানে সিনট্যাক্স এটির অনেক বেশি পুনর্লিখনের প্রয়োজন হয়।


41
@reggaeguitar আমি যদি একটি দেখতে পাই তবে আমাকে newথামতে হবে এবং ভাবতে হবে: এই পয়েন্টারটি কত দিন বেঁচে থাকবে? আমি কি এটি সঠিকভাবে পরিচালনা করেছি? যদি এর ব্যতিক্রম হয়, তবে সবকিছু কি সঠিকভাবে পরিষ্কার হয়ে যায়? আমি নিজেকে এই প্রশ্নগুলি জিজ্ঞাসা করতে এবং এতে আমার সময় নষ্ট করতে চাই না এবং যদি আমি ব্যবহার না করি তবে আমাকে newএই প্রশ্নগুলি জিজ্ঞাসা করতে হবে না।
নাথানঅলিভার

4
আপনার প্রকল্পের সমস্ত উত্স ফাইলের উপরে আপনি একটি গ্রেপ করেন এবং একটিও খুঁজে পান না new। এটা কি দুর্দান্ত হবে না?
সেবাস্তিয়ান মাচ

4
"নতুন ব্যবহার করবেন না" এর মূল সুবিধা এটির নির্দেশিকাটি সহজ, সুতরাং আপনার সাথে কাজ করা কম অভিজ্ঞ বিকাশকারীদের দেওয়া এটি একটি সহজ গাইডলাইন। আমি প্রথমে বুঝতে পারি নি, তবে এর নিজের এবং এর মূল্য রয়েছে
অনন্তকালীন

@NathanOliver আপনি আসলে না একেবারে ব্যবহার হতে হবে std::make_shared- একটি ক্ষেত্রে কল্পনা যেখানে বরাদ্দ বস্তুর বড় এবং অনেক আছে std::weak_ptrএটি -s ইশারা: এটা ভাল যাক বস্তুর গত ভাগ যত তাড়াতাড়ি মুছে যাবে হবে পয়েন্টারটি ধ্বংস হয়ে যায় এবং কেবলমাত্র একটি ছোট ভাগ করে নেওয়া অঞ্চল নিয়ে বাস করে।
দেব নুল

4
@ নাথান ওলিভার আপনি চাইবেন না আমি যে বিষয়ে কথা বলছি তা হ'ল std::make_shared স্ট্যাকওভারফ্লো . com / a / 20895705 / 8414561 এর অসুবিধা যেখানে অবজেক্টটি সংরক্ষণ করার জন্য ব্যবহৃত মেমরিটি শেষ না হওয়া পর্যন্ত মুক্ত করা যায় না std::weak_ptr(এমনকি যদি সমস্ত-ই এটি std::shared_ptrদেখায়) (এবং ফলস্বরূপ বস্তুটি নিজেই ইতিমধ্যে ধ্বংস হয়ে গেছে)।
দেব নুল

52

make_uniqueTথেকে পৃথক T[]এবং T[N], unique_ptr(new ...)না।

সহজেই আপনি একটি পয়েন্টার ছিল ক্ষণস্থায়ী দ্বারা অনির্ধারিত আচরণ পেতে পারেন new[]একটি এড unique_ptr<T>, অথবা একটি পয়েন্টার ছিল ক্ষণস্থায়ী দ্বারা newএকটি এড unique_ptr<T[]>


এটি আরও খারাপ: এটি কেবল তা নয়, এটি ফ্ল্যাট-আউটও অক্ষম।
উত্সাহক

22

ডুপ্লিকেট ছাড়াই সংক্ষিপ্ত কোড থাকার কারণ। তুলনা করা

f(std::unique_ptr<MyClass>(new MyClass(param)), g());
f(std::make_unique<MyClass>(param), g());

আপনি সংরক্ষণ করুন MyClass, newএবং ধনুর্বন্ধনী। এটা শুধুমাত্র একটি অক্ষর আরও খরচ করতে তুলনায় কাজ খুঁজছেন এরকম


4
ঠিক আছে, আমি যেমন প্রশ্নে বলেছি, কেবলমাত্র একটি উল্লেখের সাথে এটি টাইপ করা কম দেখতে পাচ্ছি MyClassতবে আমি ভাবছিলাম যে এটির ব্যবহারের আরও শক্তিশালী কারণ আছে কিনা
এটার্নাল

4
অনেক ক্ষেত্রে ছাড়ের গাইডটি <MyClass>প্রথম বৈকল্পিকের অংশটি অপসারণ করতে সহায়তা করবে ।
এএনটি

9
অন্যান্য উত্তরের জন্য মন্তব্যগুলিতে এটি ইতিমধ্যে বলা হয়েছে, তবে সি ++ 17 নির্মাণকারীদের জন্য টেমপ্লেট ধরণের ছাড়ের ক্ষেত্রে std::unique_ptrএটি অনুমোদিত নয়। এটি আলাদা করতে std::unique_ptr<T>এবংstd::unique_ptr<T[]>
শাশ্বত

19

প্রতিটি ব্যবহার newআজীবন সঠিকতার জন্য অতিরিক্ত সতর্কতার সাথে নিরীক্ষণ করতে হবে; এটি মুছে ফেলা হয়? শুধুমাত্র একবার?

প্রতিটি make_uniqueঅতিরিক্ত ব্যবহারের অতিরিক্ত বৈশিষ্ট্যগুলি নয়; এতক্ষণ যে মালিকানাধীন অবজেক্টটির "সঠিক" জীবনকাল রয়েছে, ততক্ষণ এটি অনন্য পয়েন্টারটিকে "সঠিক" করে তোলে।

এখন, এটি সত্য যে 1 থেকে 1 পর্যন্ত unique_ptr<Foo>(new Foo())সমস্তভাবে অভিন্ন ; এটির জন্য কেবল একটি সরল "আপনার উত্সের কোডগুলি অডিট করার জন্য সমস্ত ব্যবহারের জন্য গ্রেপ করুন" দরকার।make_unique<Foo>()new


1 সাধারণ ক্ষেত্রে একটি মিথ্যা। পারফেক্ট ফরওয়ার্ডিং নিখুঁত নয় {}, ডিফল্ট থিম, অ্যারেগুলি ব্যতিক্রম।


টেকনিক্যালি মোটামুটি একরকম unique_ptr<Foo>(new Foo)নয় ... পরেরটির মতো তবে অন্যথায় হ্যাঁ। make_unique<Foo>()new Foo()
ব্যারি

@ ব্যারি সত্য, অতিরিক্ত লোড অপারেটর নতুন সম্ভব।
ইয়াক্ক - অ্যাডাম নেভ্রামুমন্ট

@ এমডআপ কি ফাউল সি +++ ডাইনিট্রাফট?
ইয়াক্ক - অ্যাডাম নেভ্রামুমন্ট

4
@ ডেডুকিপেটরটি যখন সি ++ 17 কনস্ট্রাক্টরদের ক্ষেত্রে টেমপ্লেট ধরণের ছাড়ের std::unique_ptrঅনুমতি দেয় তখন তা অনুমোদিত না হয়। যদি আলাদা করতে হয় std::unique_ptr<T>এবংstd::unique_ptr<T[]>
শাশ্বত

@ ইয়াক্ক-অ্যাডামনেভ্র্যামন্ট আমি ওভারলোডিং নতুন বোঝাতে চাইছি না, আমি স্রেফ ডিফল্ট-থিম বনাম মান-থিম বোঝাতে চাইছি।
ব্যারি

0

তার পর থেকে, সি ++ 17 মূল্যায়ন আদেশটি স্পষ্ট করেছে, সিন্ট্যাক্সকেও নিরাপদ করে তুলেছে

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

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

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

(এই মূলত একই যুক্তি আমি তৈরি এখানে tuple ধ্বংসের আদেশ সম্পর্কে।)


-1

অকার্যকর ফাংশন বিবেচনা করুন (স্ট্যান্ড :: অনন্য_প্রেটার (নতুন এ ()), স্ট্যান্ড :: অনন্য_প্রেটার (নতুন বি ()) {...}

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

অকার্যকর ফাংশন (std :: make_unique (), std :: make_unique ()) {... point মূল কথাটি হ'ল std :: Make_unique এবং std :: Make_unique এখন অস্থায়ী বস্তু, এবং অস্থায়ী বস্তুর সাফাই সঠিকভাবে নির্দিষ্ট করা হয়েছে সি ++ স্ট্যান্ডার্ড: তাদের ধ্বংসকারীদের ট্রিগার করা হবে এবং মেমরিটি মুক্ত করা হবে। সুতরাং আপনি যদি পারেন তবে সর্বদা std :: Make_unique এবং std :: make_shared ব্যবহার করে অবজেক্টগুলি বরাদ্দ করতে পছন্দ করুন।


4
লেখক স্পষ্টভাবে প্রশ্নে নির্দিষ্ট করেছেন যে সি ++ এ 17 টি ফাঁস আর হবে না। "তার পর থেকে সি ++ 17 মূল্যায়ন আদেশকে স্পষ্ট করে দিয়েছে, সিনট্যাক্সকেও নিরাপদ করে তুলেছে, সুতরাং আমার প্রশ্নটি এখানে: (...)"। আপনি তাঁর প্রশ্নের উত্তর দেন নি।
R2RT
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.