নির্দিষ্ট আকার
1. রেফারেন্স দ্বারা পাস
template <size_t rows, size_t cols>
void process_2d_array_template(int (&array)[rows][cols])
{
std::cout << __func__ << std::endl;
for (size_t i = 0; i < rows; ++i)
{
std::cout << i << ": ";
for (size_t j = 0; j < cols; ++j)
std::cout << array[i][j] << '\t';
std::cout << std::endl;
}
}
সি ++ তে মাত্রা সম্পর্কিত তথ্য না হারিয়ে রেফারেন্স দিয়ে অ্যারে পাস করা সম্ভবত সবচেয়ে নিরাপদ, যেহেতু কলারকে একটি ভুল মাত্রা (অমিলের সময় সংকলক পতাকাগুলি) পাস করার বিষয়ে চিন্তা করার দরকার নেই। তবে গতিশীল (ফ্রিস্টোর) অ্যারে দিয়ে এটি সম্ভব নয়; এটি কেবল স্বয়ংক্রিয়ভাবে ( সাধারণত স্ট্যাক-লিভিং ) অ্যারেগুলির জন্য কাজ করে, মাত্রাটি সংকলনের সময় জানা উচিত।
2. পয়েন্টার দ্বারা পাস
void process_2d_array_pointer(int (*array)[5][10])
{
std::cout << __func__ << std::endl;
for (size_t i = 0; i < 5; ++i)
{
std::cout << i << ": ";
for (size_t j = 0; j < 10; ++j)
std::cout << (*array)[i][j] << '\t';
std::cout << std::endl;
}
}
পূর্ববর্তী পদ্ধতির সি সমতুল্য পয়েন্টার দ্বারা অ্যারে পাস করছে। এটি অ্যারের ক্ষয় পয়েন্টার টাইপ (3) দিয়ে যাওয়ার সাথে বিভ্রান্ত হওয়া উচিত নয় , যা সাধারণ, জনপ্রিয় পদ্ধতি এটি এর চেয়ে কম সুরক্ষিত হলেও আরও নমনীয়। (1) এর মতো এই পদ্ধতিটি ব্যবহার করুন যখন অ্যারের সমস্ত মাত্রা সংশোধন করা হয় এবং সংকলন সময়ে জানা যায়। নোট করুন যে ফাংশনটি কল করার সময় অ্যারের ঠিকানাটি পাস করা উচিত process_2d_array_pointer(&a)
এবং ক্ষয় দ্বারা প্রথম উপাদানটির ঠিকানাটি নয় process_2d_array_pointer(a)
।
পরিবর্তনশীল আকার
এগুলি সি থেকে উত্তরাধিকার সূত্রে প্রাপ্ত তবে কম নিরাপদ, সংকলকটির কাছে পরীক্ষা করার কোনও উপায় নেই, গ্যারান্টি দিয়ে যে কলার প্রয়োজনীয় মাত্রাটি পার করছে। ফাংশনটি কেবলমাত্র কলার যা মাত্রা (গুলি) হিসাবে পাস করে তার উপর ব্যাঙ্ক করে। এগুলি উপরোক্তগুলির তুলনায় আরও নমনীয় কারণ বিভিন্ন দৈর্ঘ্যের অ্যারে তাদের কাছে অবিচ্ছিন্নভাবে দেওয়া যেতে পারে।
এটি মনে রাখতে হবে যে সিতে কোনও ক্রিয়াকলাপে সরাসরি অ্যারে পাস করার মতো কোনও বিষয় নেই [সি ++ থাকা অবস্থায় এগুলি রেফারেন্স হিসাবে (1) ] পাস করা যেতে পারে ; (২) অ্যারেতে একটি পয়েন্টার দিয়ে যাচ্ছে এবং অ্যারে নিজেই নয়। সর্বদা যেমন বিন্যাসকে যেমন করা হয় তেমন পয়েন্টার-অনুলিপি অপারেশন হয়ে যায় যা অ্যারে এর বিন্দুতে ক্ষয় হওয়ার প্রকৃতি দ্বারা সহজতর হয় ।
3. ক্ষয়প্রাপ্ত টাইপের একটি পয়েন্টার (মান) দ্বারা পাস করুন
// int array[][10] is just fancy notation for the same thing
void process_2d_array(int (*array)[10], size_t rows)
{
std::cout << __func__ << std::endl;
for (size_t i = 0; i < rows; ++i)
{
std::cout << i << ": ";
for (size_t j = 0; j < 10; ++j)
std::cout << array[i][j] << '\t';
std::cout << std::endl;
}
}
যদিও int array[][10]
অনুমোদিত, আমি উপরের সিনট্যাক্সের উপরে এটির সুপারিশ করব না কারণ উপরের সিনট্যাক্সটি এটি পরিষ্কার করে দিয়েছে যে সনাক্তকারীটি array
10 টি পূর্ণসংখ্যার অ্যারের একক পয়েন্টার, যখন এই বাক্য গঠনটি 2D অ্যারের মতো দেখায় তবে এটি একই পয়েন্টার হিসাবে একই 10 পূর্ণসংখ্যার অ্যারে। এখানে আমরা একক সারিতে উপাদানের সংখ্যা জানি (যেমন কলামের আকার, 10 এখানে) তবে সারিগুলির সংখ্যা অজানা এবং সুতরাং একটি আর্গুমেন্ট হিসাবে পাস করার জন্য। এই ক্ষেত্রে কিছুটা সুরক্ষা আছে যেহেতু সংকলকটি পতাকাঙ্কিত করতে পারে যখন 10 এর সমান নয় দ্বিতীয় স্তরের একটি অ্যারেরের পয়েন্টারটি পাস করা হয়। প্রথম মাত্রা হ'ল বিবিধ অংশ এবং বাদ দেওয়া যায়। কেন কেবল প্রথম মাত্রা বাদ দেওয়া যেতে পারে তার যুক্তিযুক্ততার জন্য এখানে দেখুন ।
4. একটি পয়েন্টার দ্বারা পয়েন্টার দ্বারা পাস
// int *array[10] is just fancy notation for the same thing
void process_pointer_2_pointer(int **array, size_t rows, size_t cols)
{
std::cout << __func__ << std::endl;
for (size_t i = 0; i < rows; ++i)
{
std::cout << i << ": ";
for (size_t j = 0; j < cols; ++j)
std::cout << array[i][j] << '\t';
std::cout << std::endl;
}
}
আবার একটি বিকল্প বাক্য গঠন আছে int *array[10]
যা এর সমান int **array
। এই সিনট্যাক্সে এটি [10]
পয়েন্টার হিসাবে ক্ষয়িষ্ণু হয়ে ওঠার সাথে সাথে এটি উপেক্ষা করা হয় int **array
। সম্ভবত এটি কলারের কাছে কেবল একটি সূত্র যা উত্তীর্ণ অ্যারেতে কমপক্ষে 10 টি কলাম থাকতে হবে, তারপরেও সারি গণনা প্রয়োজন। যে কোনও ক্ষেত্রে সংকলকটি কোনও দৈর্ঘ্য / আকার লঙ্ঘনের জন্য পতাকাঙ্কণ করে না (এটি কেবল পরীক্ষিত টাইপটি পয়েন্টারের কাছে নির্দেশক কিনা তা কেবল এটি পরীক্ষা করে), সুতরাং এখানে প্যারামিটারটি বোঝার জন্য সারি এবং কলাম উভয়ই প্রয়োজন।
দ্রষ্টব্য: (4) হ'ল ন্যূনতম সুরক্ষিত বিকল্প কারণ এটির মধ্যে কোনও ধরণের চেক এবং খুব অসুবিধা নেই। কেউ এই ফাংশনে বৈধভাবে 2D অ্যারে পাস করতে পারবেন না; সি-এফএকিউ স্বাভাবিক ক্রিয়াকলাপটিকে নিন্দা করে int x[5][10]; process_pointer_2_pointer((int**)&x[0][0], 5, 10);
কারণ এটি অ্যারে ফ্ল্যাটিংয়ের কারণে সম্ভাব্যরূপে সংজ্ঞায়িত আচরণের দিকে পরিচালিত করতে পারে । এই পদ্ধতিতে একটি অ্যারে পাস করার সঠিক উপায়টি আমাদের অসুবিধার অংশে নিয়ে আসে অর্থাৎ আমাদের প্রতিটি এলিমেন্টের সাথে পয়েন্টারের অতিরিক্ত (সারোগেট) অ্যারের প্রয়োজন যা প্রকৃত, বি-পাস-করা অ্যারের সম্পর্কিত রেখায় নির্দেশ করে; এই সারোগেটটি তখন ফাংশনে পাস করা হয় (নীচে দেখুন); উপরের পদ্ধতিগুলির মতো একই কাজটি করার জন্য যা আরও নিরাপদ, ক্লিনার এবং সম্ভবত দ্রুত।
উপরের ফাংশনগুলি পরীক্ষা করার জন্য এখানে একটি ড্রাইভার প্রোগ্রাম রয়েছে:
#include <iostream>
// copy above functions here
int main()
{
int a[5][10] = { { } };
process_2d_array_template(a);
process_2d_array_pointer(&a); // <-- notice the unusual usage of addressof (&) operator on an array
process_2d_array(a, 5);
// works since a's first dimension decays into a pointer thereby becoming int (*)[10]
int *b[5]; // surrogate
for (size_t i = 0; i < 5; ++i)
{
b[i] = a[i];
}
// another popular way to define b: here the 2D arrays dims may be non-const, runtime var
// int **b = new int*[5];
// for (size_t i = 0; i < 5; ++i) b[i] = new int[10];
process_pointer_2_pointer(b, 5, 10);
// process_2d_array(b, 5);
// doesn't work since b's first dimension decays into a pointer thereby becoming int**
}