উত্পন্ন বস্তুর একটি অ্যারে বেস পয়েন্টার একটি পয়েন্টার করতে পারেন?


99

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

মেমরি ফাঁস এবং সত্যই কোনও ভার্চুয়াল ডটার নেই, কেন এই কোডটি ক্রাশ হয়?

#include <iostream>

//besides the obvious mem leak, why does this code crash?

class Shape
{
public:
    virtual void draw() const = 0;
};

class Circle : public Shape
{
public:
    virtual void draw() const { }

    int radius;
};

class Rectangle : public Shape
{
public:
    virtual void draw() const { }

    int height;
    int width;
};

int main()
{
    Shape * shapes = new Rectangle[10];
    for (int i = 0; i < 10; ++i)
        shapes[i].draw();
}

4
হারিয়ে যাওয়া সেমিকোলন ছাড়াও? (এটি একটি সংকলন-সময় ত্রুটি হবে, যদিও রানটাইম নয়)
প্ল্যাটিনাম আজুর

আপনি কি নিশ্চিত যে তারা সবাই ভার্চুয়াল ছিলেন?
ইয়োচাই টিমমার

8
এটি হওয়া উচিত Shape **এটি আয়তক্ষেত্রের একটি অ্যারের দিকে নির্দেশ করছে। তারপরে অ্যাক্সেসের আকার হওয়া উচিত ছিল [i] -> অঙ্কন ();
রেডএক্স

4
@ টনি শুভকামনা, আমাদের অবহিত করুন :)
শেঠ কার্নেগি

4
@ অ্যান্ড্রেটি: কোডটি এখন সঠিক (এবং মূলত এটিও সঠিক ছিল)। ->ভুল একজন সম্পাদক দ্বারা তৈরি ছিল।
আর মার্টিনহো ফার্নান্দিস

উত্তর:


150

আপনি এর মতো সূচী করতে পারবেন না। আপনি একটি অ্যারের বরাদ্দ করেছেন Rectanglesএবং প্রথমটিতে একটি পয়েন্টার সঞ্চয় করেছেন shapes। যখন আপনি করবেন shapes[1]আপনি dereferences করছেন (shapes + 1)। এটি আপনাকে পরবর্তীটির জন্য একটি পয়েন্টার দেবে না Rectangle, তবে Shapeঅনুমান করা অ্যারেতে পরবর্তীটি কী হবে তার একটি পয়েন্টার Shape। অবশ্যই, এটি অনির্ধারিত আচরণ। আপনার ক্ষেত্রে, আপনি ভাগ্যবান এবং ক্র্যাশ পেয়ে যাচ্ছেন।

Rectangleসূচকে সঠিকভাবে কাজ করতে পয়েন্টার ব্যবহার করা।

int main()
{
   Rectangle * shapes = new Rectangle[10];
   for (int i = 0; i < 10; ++i) shapes[i].draw();
}

আপনি যদি Shapeঅ্যারেতে বিভিন্ন ধরণের গুলি রাখতে চান এবং সেগুলি বহুবচিকভাবে ব্যবহার করতে চান তবে আপনাকে আকারের জন্য পয়েন্টারের একটি অ্যারের প্রয়োজন ।


37

মার্টিনহো ফার্নান্দিস যেমন বলেছিলেন, তর্জনীকরণটি ভুল। আপনি যদি এর পরিবর্তে শেপের একটি অ্যারে সঞ্চয় করতে চান তবে আপনাকে শেপ * এর অ্যারে ব্যবহার করে এটি করতে হবে:

int main()
{
   Shape ** shapes = new Shape*[10];
   for (int i = 0; i < 10; ++i) shapes[i] = new Rectangle;
   for (int i = 0; i < 10; ++i) shapes[i]->draw();
}

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


13

কোনও পয়েন্টারকে সূচক করার সময়, সংকলক অ্যারের ভিতরে যা রয়েছে তার আকারের ভিত্তিতে উপযুক্ত পরিমাণ যুক্ত করবে। সুতরাং সেই আকারটি (আকার) = 4 বলুন (কারণ এতে কোনও সদস্যের ভেরিয়েবল নেই)। তবে আকারের (আয়তক্ষেত্র) = 12 (সঠিক সংখ্যা সম্ভবত ভুল)।

সুতরাং আপনি যখন সূচকটি প্রথম এলিমেন্টের জন্য ... 0x0 বলতে শুরু করবেন, তারপরে আপনি যখন 10 তম উপাদানটি অ্যাক্সেস করার চেষ্টা করবেন তখন আপনি কোনও অবৈধ ঠিকানা বা কোনও অবস্থানে যাচ্ছেন যা অবজেক্টের শুরু নয়।


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