নাল্পটারের মূল কথা
std::nullptr_t
নাল পয়েন্টার আক্ষরিক, নালপ্ট্রারের ধরণ। এটা তোলে ধরনের prvalue / rvalue হয় std::nullptr_t
। নালপ্ট্রার থেকে কোনও পয়েন্টার ধরণের নাল পয়েন্টার মান পর্যন্ত অন্তর্নিহিত রূপান্তর রয়েছে।
আক্ষরিক 0 একটি ইনট, কোনও পয়েন্টার নয়। যদি সি ++ যদি নিজেকে এমন একটি প্রসঙ্গে দেখায় যেখানে কেবলমাত্র পয়েন্টার ব্যবহার করা যায় তবে এটি হতাশাজনকভাবে 0 টি নাল পয়েন্টার হিসাবে ব্যাখ্যা করবে, তবে এটি একটি ফ্যালব্যাক অবস্থান। সি ++ এর প্রাথমিক নীতিটি হ'ল 0 টি একটি ইনট, কোনও পয়েন্টার নয়।
সুবিধা 1 - পয়েন্টার এবং ইন্টিগ্রাল ধরণের ওভারলোডিংয়ের সময় অস্পষ্টতা সরিয়ে ফেলুন
সি ++৯-এ, এর প্রাথমিক ধারণাটি হ'ল পয়েন্টার এবং অবিচ্ছেদ্য ধরণের উপর ওভারলোডিং বিস্মিত হতে পারে। এই ধরনের ওভারলোডগুলিতে 0 বা NULL পাস করা কখনই পয়েন্টার ওভারলোড নামে ডাকা হয় না:
void fun(int); // two overloads of fun
void fun(void*);
fun(0); // calls f(int), not fun(void*)
fun(NULL); // might not compile, but typically calls fun(int). Never calls fun(void*)
এই কলটির সম্পর্কে আকর্ষণীয় বিষয় হ'ল উত্স কোডের আপাত অর্থ ("আমি নুল-নাল পয়েন্টারটির সাথে মজা করছি") এবং এর আসল অর্থ ("আমি কিছুটা পূর্ণসংখ্যার সাথে মজা বলছি - নাল নয়) পয়েন্টার ")।
নাল্প্ট্রারের সুবিধা হ'ল এতে অবিচ্ছেদ্য প্রকার নেই। নালপ্টারের সাথে ওভারলোড হওয়া ফাংশনটিকে মজাদার কলটি অকার্যকর * ওভারলোড (অর্থাত্ পয়েন্টার ওভারলোড) বলে, কারণ নালপ্টরকে অবিচ্ছেদ্য কিছু হিসাবে দেখা যায় না:
fun(nullptr); // calls fun(void*) overload
0 বা NULL এর পরিবর্তে নালপ্ট্রার ব্যবহার করে ওভারলোডের রেজোলিউশনগুলি অবাক করে দেয়।
রিটার্ন টাইপের জন্য অটো ব্যবহার করার পরে nullptr
ওভারের আরেকটি সুবিধাNULL(0)
উদাহরণস্বরূপ, ধরুন আপনি একটি কোড বেসে এটির মুখোমুখি হয়েছেন:
auto result = findRecord( /* arguments */ );
if (result == 0) {
....
}
যদি আপনি রেকর্ড কী ফাইন্ডারটি জানেন (বা সহজেই তা আবিষ্কার করতে না পারেন) তবে ফলাফলটি পয়েন্টার টাইপ বা ইন্টিগ্রাল টাইপ কিনা তা পরিষ্কার নয় be সর্বোপরি, 0 (কী ফলাফলের বিরুদ্ধে পরীক্ষিত হয়) যে কোনও পথে যেতে পারে। আপনি যদি নীচে দেখতে পান তবে অন্যদিকে,
auto result = findRecord( /* arguments */ );
if (result == nullptr) {
...
}
কোনও অস্পষ্টতা নেই: ফলাফল অবশ্যই পয়েন্টারের ধরণের হতে হবে।
সুবিধা 3
#include<iostream>
#include <memory>
#include <thread>
#include <mutex>
using namespace std;
int f1(std::shared_ptr<int> spw) // call these only when
{
//do something
return 0;
}
double f2(std::unique_ptr<int> upw) // the appropriate
{
//do something
return 0.0;
}
bool f3(int* pw) // mutex is locked
{
return 0;
}
std::mutex f1m, f2m, f3m; // mutexes for f1, f2, and f3
using MuxtexGuard = std::lock_guard<std::mutex>;
void lockAndCallF1()
{
MuxtexGuard g(f1m); // lock mutex for f1
auto result = f1(static_cast<int>(0)); // pass 0 as null ptr to f1
cout<< result<<endl;
}
void lockAndCallF2()
{
MuxtexGuard g(f2m); // lock mutex for f2
auto result = f2(static_cast<int>(NULL)); // pass NULL as null ptr to f2
cout<< result<<endl;
}
void lockAndCallF3()
{
MuxtexGuard g(f3m); // lock mutex for f2
auto result = f3(nullptr);// pass nullptr as null ptr to f3
cout<< result<<endl;
} // unlock mutex
int main()
{
lockAndCallF1();
lockAndCallF2();
lockAndCallF3();
return 0;
}
উপরের প্রোগ্রামটি সংকলন করে এবং সফলভাবে সম্পাদন করা হয়েছে তবে লকঅ্যান্ডক্যালএফ 1, লকআ্যান্ডএলক্যালএফ 2 এবং লকঅ্যান্ডক্যালএফ 3 এর রিডান্ট্যান্ট কোড রয়েছে। আমরা যদি এই সমস্তটির জন্য টেমপ্লেট লিখতে পারি তবে এই জাতীয় কোডটি লেখার জন্য দুঃখ হয় lockAndCallF1, lockAndCallF2 & lockAndCallF3
। সুতরাং এটি টেমপ্লেট দিয়ে সাধারণীকরণ করা যায়। অপ্রয়োজনীয় কোডের জন্য আমি lockAndCall
একাধিক সংজ্ঞার পরিবর্তে টেম্পলেট ফাংশন লিখেছি lockAndCallF1, lockAndCallF2 & lockAndCallF3
।
কোডটি নীচের মতো পুনঃসংশ্লিষ্ট:
#include<iostream>
#include <memory>
#include <thread>
#include <mutex>
using namespace std;
int f1(std::shared_ptr<int> spw) // call these only when
{
//do something
return 0;
}
double f2(std::unique_ptr<int> upw) // the appropriate
{
//do something
return 0.0;
}
bool f3(int* pw) // mutex is locked
{
return 0;
}
std::mutex f1m, f2m, f3m; // mutexes for f1, f2, and f3
using MuxtexGuard = std::lock_guard<std::mutex>;
template<typename FuncType, typename MuxType, typename PtrType>
auto lockAndCall(FuncType func, MuxType& mutex, PtrType ptr) -> decltype(func(ptr))
//decltype(auto) lockAndCall(FuncType func, MuxType& mutex, PtrType ptr)
{
MuxtexGuard g(mutex);
return func(ptr);
}
int main()
{
auto result1 = lockAndCall(f1, f1m, 0); //compilation failed
//do something
auto result2 = lockAndCall(f2, f2m, NULL); //compilation failed
//do something
auto result3 = lockAndCall(f3, f3m, nullptr);
//do something
return 0;
}
বিস্তারিত বিশ্লেষণ কেন সংকলন ব্যর্থ lockAndCall(f1, f1m, 0) & lockAndCall(f3, f3m, nullptr)
নাlockAndCall(f3, f3m, nullptr)
সংকলন কেন lockAndCall(f1, f1m, 0) & lockAndCall(f3, f3m, nullptr)
ব্যর্থ?
সমস্যাটি হ'ল 0 টি লকএন্ডকালে পাস করা হয়, টেম্পলেট টাইপ ছাড়ের প্রকারটি খুঁজে বের করতে তার প্রকারটি বের করতে। 0 এর ধরণটি int হয়, সুতরাং এটি লকএন্ডক্যাল-এ এই কলটির ইনস্ট্যান্টেশনের ভিতরে প্যারামিটার পিটিআর টাইপ। দুর্ভাগ্যক্রমে, এর অর্থ এটি হ'ল লকএন্ডকালের অভ্যন্তরে ফান করার কলটিতে, একটি ইনট পাস হচ্ছে এবং এটি যে std::shared_ptr<int>
পরামিতিটি f1
প্রত্যাশা করে তার সাথে সামঞ্জস্য নয় । কলটিতে পাস করা 0 টি lockAndCall
নাল পয়েন্টার উপস্থাপনের উদ্দেশ্যে করা হয়েছিল, তবে আসলে যা পাস করেছে তা হ'ল ইনট। এই std::shared_ptr<int>
প্রকারটি এফ 1 এ পাস করার চেষ্টা করা এক ধরণের ত্রুটি। lockAndCall
0 সহ কলটি ব্যর্থ হয় কারণ টেম্পলেটটির অভ্যন্তরে একটি ক্রিয়াকলাপের জন্য একটি প্রেরণ করা হচ্ছে যার জন্য একটি প্রয়োজন std::shared_ptr<int>
।
জড়িত কলটির বিশ্লেষণ NULL
মূলত একই is যখন NULL
পাস করা হয় lockAndCall
, তখন প্যারামিটার পিটিআর জন্য একটি অবিচ্ছেদ্য প্রকারকে অনুমিত করা হয় এবং ptr
—an int বা int-like টাইপ to এ পাস করার পরে একটি টাইপ ত্রুটি ঘটে থাকে f2
যা একটি পাওয়ার আশা করে std::unique_ptr<int>
।
বিপরীতে, জড়িত কলটিতে nullptr
কোনও সমস্যা নেই। যখন nullptr
পাস করা হয় lockAndCall
, এর জন্য টাইপটি ptr
হ্রাস করা হয় std::nullptr_t
। কখন ptr
পাস করা হয় f3
, সেখানে থেকে একটি অন্তর্নিহিত রূপান্তর std::nullptr_t
আছে int*
, কারণ std::nullptr_t
স্পষ্টতই সমস্ত পয়েন্টার ধরণের রূপান্তরিত হয়।
এটি প্রস্তাবিত হয়, যখনই আপনি নাল পয়েন্টারটি উল্লেখ করতে চান, নলপ্টার ব্যবহার করুন, 0 বা নয় NULL
।
int
এবংvoid *
পছন্দ করে নিন করা হবে নাint
উপর সংস্করণvoid *
ব্যবহার করে যখন সংস্করণnullptr
।