এখানে বেশিরভাগ উত্তরই অভিপ্রায় প্রকাশের শর্তে কোনও ফাংশন স্বাক্ষরে কাঁচা পয়েন্টার রাখার সহজাত অস্পষ্টতাকে সম্বোধন করতে ব্যর্থ হয়। সমস্যাগুলি নিম্নলিখিত:
কলার জানে না যে পয়েন্টারটি কোনও একক বস্তুতে নির্দেশ করে, বা বস্তুর "অ্যারে" শুরু করতে পারে কিনা।
কলার জানে না যে পয়েন্টারটি মেমোরিটিকে নির্দেশ করে এটি "মালিকানাধীন" কিনা। IE, ফাংশনটির স্মৃতি মুক্ত হওয়া উচিত কিনা। ( foo(new int)
- এটি কি স্মৃতি ফুটো?)।
কলকারী জানেন nullptr
না যে নিরাপদে ফাংশনে প্রবেশ করতে পারবেন কি না ।
এই সমস্ত সমস্যার সমাধান দ্বারা সমাধান করা হয়:
রেফারেন্স সর্বদা একটি একক বস্তুর উল্লেখ করে।
রেফারেন্সগুলি তারা যে মেমরিটিকে উল্লেখ করে তার মালিক নয়, এগুলি কেবল মেমরির মধ্যে একটি দৃষ্টিভঙ্গি।
তথ্যসূত্রগুলি নਾਲ হতে পারে না।
এটি রেফারেন্সগুলি সাধারণ ব্যবহারের জন্য আরও ভাল প্রার্থী করে তোলে। তবে, উল্লেখগুলি নিখুঁত নয় - কয়েকটি বড় সমস্যা বিবেচনা করতে হবে।
- কোনও স্পষ্ট নির্দেশনা নেই ction এটি কোনও কাঁচা পয়েন্টার নিয়ে সমস্যা নয়, কারণ আমরা
&
প্রকৃতপক্ষে কোনও পয়েন্টারটি পাস করছি তা দেখানোর জন্য অপারেটরটি ব্যবহার করতে হবে। উদাহরণস্বরূপ, int a = 5; foo(a);
এটি এখানে মোটেও পরিষ্কার নয় যে একটি রেফারেন্স দ্বারা পাস হচ্ছে এবং এটি সংশোধন করা যেতে পারে।
- Nullability। পয়েন্টারগুলির এই দুর্বলতাও একটি শক্তি হতে পারে, যখন আমরা প্রকৃতপক্ষে আমাদের রেফারেন্সগুলি নালাগুলি করতে চাই ।
std::optional<T&>
বৈধ নয় হিসাবে দেখা (ভাল কারণে), পয়েন্টারগুলি আপনাকে যে নালিয়াটি চান তা দেয়।
সুতরাং দেখে মনে হচ্ছে যে আমরা যখন সুস্পষ্ট ইন্ডিয়ারেশন সহ একটি অযোগ্য রেফারেন্স চাই তখন আমাদের কোনও T*
অধিকারের জন্য পৌঁছানো উচিত ? ভুল!
abstractions
অকার্যকরতার জন্য আমাদের হতাশায় আমরা T*
প্রথমে তালিকাভুক্ত সমস্ত ত্রুটি এবং শব্দার্থক অস্পষ্টতা উপেক্ষা করতে পারি এবং তা উপেক্ষা করতে পারি । পরিবর্তে, আমাদের সি ++ সবচেয়ে ভাল যা করতে পারে তার জন্য পৌঁছানো উচিত: একটি বিমূর্ততা। যদি আমরা কেবল এমন একটি ক্লাস লিখি যা কোনও পয়েন্টারের চারপাশে আবৃত হয়, আমরা অভিব্যক্তিটি অর্জন করি, পাশাপাশি শূণ্যতা এবং স্পষ্ট ইন্ডিরেশনও অর্জন করি।
template <typename T>
struct optional_ref {
optional_ref() : ptr(nullptr) {}
optional_ref(T* t) : ptr(t) {}
optional_ref(std::nullptr_t) : ptr(nullptr) {}
T& get() const {
return *ptr;
}
explicit operator bool() const {
return bool(ptr);
}
private:
T* ptr;
};
এটি আমি নিয়ে আসা সবচেয়ে সহজ ইন্টারফেস, কিন্তু কার্যকরভাবে এটি কাজ করে। এটি রেফারেন্স সূচনা করার জন্য, কোনও মান বিদ্যমান কিনা তা পরীক্ষা করে এবং মানটি অ্যাক্সেস করার অনুমতি দেয়। আমরা এটি এর মতো ব্যবহার করতে পারি:
void foo(optional_ref<int> x) {
if (x) {
auto y = x.get();
// use y here
}
}
int x = 5;
foo(&x); // explicit indirection here
foo(nullptr); // nullability
আমরা আমাদের লক্ষ্য অর্জন করেছি! আসুন এখন কাঁচা পয়েন্টারের তুলনায় সুবিধাগুলি দেখুন।
- ইন্টারফেসটি পরিষ্কারভাবে দেখায় যে রেফারেন্সটি কেবলমাত্র একটি অবজেক্টকে উল্লেখ করা উচিত।
- স্পষ্টতই এটি যে মেমরিটিকে উল্লেখ করে তার মালিকানা তার নেই, কারণ এতে কোনও ব্যবহারকারীর সংজ্ঞায়িত ডেস্ট্রাক্টর নেই এবং মেমরি মোছার কোনও পদ্ধতি নেই।
- কলকারী জানেন
nullptr
যে পাস করা যেতে পারে, যেহেতু ফাংশন লেখক স্পষ্টভাবে একটি জন্য জিজ্ঞাসা করছেনoptional_ref
আমরা এখান থেকে ইন্টারফেসটিকে আরও জটিল করে তুলতে পারি, যেমন সমতা অপারেটর যুক্ত করা, একটি monadic get_or
এবং map
ইন্টারফেস, একটি পদ্ধতি যা মূল্য পায় বা একটি ব্যতিক্রম, constexpr
সমর্থন ছুঁড়ে । আপনার দ্বারা এটি করা যেতে পারে।
উপসংহারে, কাঁচা পয়েন্টার ব্যবহার করার পরিবর্তে, আপনার পয়েন্টারগুলিতে আপনার পয়েন্টারগুলি আসলে কী বোঝায় সে সম্পর্কে যুক্তিযুক্ত কারণ এবং কোনও মানক গ্রন্থাগার বিমূর্তিটি উপস্থাপন করুন বা আপনার নিজের লিখুন। এটি আপনার কোডকে উল্লেখযোগ্যভাবে উন্নত করবে।
new
একটি পয়েন্টার তৈরি করতে এবং মালিকানার ফলস্বরূপ সমস্যাগুলি ভুলে যাবেন না ।