কেন দুবার ধ্বংসকারীকে মৃত্যুদণ্ড দেওয়া হয়েছিল?


12
#include <iostream>
using namespace std;

class Car
{
public:
    ~Car()  { cout << "Car is destructed." << endl; }
};

class Taxi :public Car
{
public:
    ~Taxi() {cout << "Taxi is destructed." << endl; }
};

void test(Car c) {}

int main()
{
    Taxi taxi;
    test(taxi);
    return 0;
}

এটি আউটপুট :

Car is destructed.
Car is destructed.
Taxi is destructed.
Car is destructed.

আমি এমএস ভিজ্যুয়াল স্টুডিও সম্প্রদায় 2017 ব্যবহার করি (দুঃখিত, ভিজ্যুয়াল সি ++ এর সংস্করণটি কীভাবে দেখতে হবে তা আমি জানি না)। আমি যখন ডিবাগ মোড ব্যবহার করি। void test(Car c){ }প্রত্যাশা অনুযায়ী ফাংশন বডি ছেড়ে যাওয়ার সময় আমি একজন ডেস্ট্রাক্টর মৃত্যুদন্ড কার্যকর করি । আর একটি অতিরিক্ত বিনাশকারী হাজির যখন test(taxi);শেষ হয়ে গেছে।

test(Car c)ফাংশন আনুষ্ঠানিক প্যারামিটার হিসাবে মান ব্যবহার করে। ফাংশনে যাওয়ার সময় একটি গাড়ি অনুলিপি করা হয়। সুতরাং আমি ভেবেছিলাম ফাংশনটি ছাড়ার সময় কেবল একটি "গাড়ি ধ্বংস হয়"। তবে কার্যকারিতাটি ছেড়ে যাওয়ার সময় দুটি "গাড়ি ধ্বংস হয়" ((আউটপুটে প্রদর্শিত প্রথম এবং দ্বিতীয় লাইন) সেখানে দুটি "গাড়ি ধ্বংস হয়" কেন? ধন্যবাদ.

===============

যখন আমি class Car উদাহরণস্বরূপ কোনও ভার্চুয়াল ফাংশন যুক্ত করব : virtual void drive() {} তারপরে আমি প্রত্যাশিত আউটপুট পাব।

Car is destructed.
Taxi is destructed.
Car is destructed.

3
কোনও বিষয় যখন কোনও মান দ্বারা কোনও বস্তু গ্রহণ করে কোনও ক্রিয়াকলাপে পাস করার সময় সংকলক কীভাবে বস্তুটি স্লাইসিং পরিচালনা করে তা একটি সমস্যা হতে পারে ? TaxiCar
কিছু প্রোগ্রামার ড্যুড

1
আপনার পুরানো সি ++ সংকলক হতে হবে। g ++ 9 প্রত্যাশিত ফলাফল দেয়। কী কারণে অবজেক্টের অতিরিক্ত কপি তৈরি করা হয় তা নির্ধারণ করতে একটি ডিবাগার ব্যবহার করুন।
স্যাম বর্ষাভিক

2
আমি +.৪.০ সংস্করণ সহ জি ++ এবং 6.০.০ সংস্করণ সহ ঝাঁকুনি ++ পরীক্ষা করেছি। তারা প্রত্যাশিত আউটপুট দিয়েছে যা অপের আউটপুট থেকে পৃথক। সুতরাং সমস্যাটি তিনি ব্যবহার করেন এমন সংকলক সম্পর্কে হতে পারে।
Marceline

1
আমি এমএস ভিজ্যুয়াল সি ++ দিয়ে পুনরুত্পাদন করেছি। যদি আমি কোনও ব্যবহারকারী-সংজ্ঞায়িত অনুলিপি-কন্সট্রাক্টর এবং ডিফল্ট Carনির্মাতা যুক্ত করি তবে এই সমস্যাটি অদৃশ্য হয়ে যায় এবং এটি প্রত্যাশিত ফলাফল দেয়।
ইন্টারজয়

1
দয়া করে প্রশ্নের সংকলক এবং সংস্করণ যুক্ত করুন
লাইটনেস রেস

উত্তর:


7

দেখে মনে হচ্ছে ভিজ্যুয়াল স্টুডিও সংকলকটি taxiফাংশন কলের জন্য আপনার টুকরো টুকরো করার সময় কিছুটা শর্টকাট নিচ্ছে , যার ফলস্বরূপ ফলাফল এটি প্রত্যাশার চেয়ে বেশি কাজ করে।

প্রথমত, এটি আপনার গ্রহণ করছে taxiএবং Carএটি থেকে একটি অনুলিপি তৈরি করছে, যাতে যুক্তিটি মিলছে।

তারপরে, এটি পাস-বাই-মানটির জন্য Car আবার অনুলিপি করছে ।

আপনি যখন কোনও ব্যবহারকারী-সংজ্ঞায়িত অনুলিপি নির্মাণকারীকে যুক্ত করেন তখন এই আচরণটি সরে যায়, সুতরাং সংকলকটি তার নিজস্ব কারণে (সম্ভবত অভ্যন্তরীণভাবে এটি একটি সহজ কোড পাথ) এটি ব্যবহার করছে বলে মনে হয় কারণ এটি "অনুমোদিত" কারণ অনুলিপি নিজেই তুচ্ছ। আপনি এখনও তুচ্ছ-বিবাদী ডেস্ট্রাক্টর ব্যবহার করে এই আচরণটি পর্যবেক্ষণ করতে পারেন তা হ'ল কিছুটা হ্রাস করা।

আমি জানি না যে এটি কতটা বৈধ (বিশেষত সি ++ 17), বা সংকলক কেন এই পদ্ধতিকে গ্রহণ করবে, তবে আমি সম্মত হব যে এটি আউটপুট যা আমি স্বজ্ঞাতভাবে প্রত্যাশা করেছিলাম তা নয়। জিসিসি বা ক্ল্যাং কেউই এটি করে না, যদিও এটি হতে পারে যে তারা একইভাবে কাজ করে তবে অনুলিপিটি সরিয়ে দেওয়ার ক্ষেত্রে আরও ভাল। আমি আছে লক্ষ্য করেছি যে, এমনকি বনাম 2019 এখনও নিশ্চিত বিলোপ এ মহান নয়।


দুঃখিত, তবে আমি ঠিক এই কথাটি বলেছি না "যদি আপনার সংকলক কপি এলিজেন না করে তবে ট্যাক্সি থেকে গাড়ীতে রূপান্তর"।
ক্রিস্টোফ

এটি একটি অন্যায্য মন্তব্য, কারণ এই প্রশ্নটি ছাড়িয়ে ওপিকে সহায়তা করার জন্য, কাটা কাটা এড়াতে রেফারেন্সের মাধ্যমে মান বনাম পাসটি কেবল একটি সম্পাদনায় যুক্ত করা হয়েছিল। তারপরে আমার উত্তরটি অন্ধকারের মধ্যে শট ছিল না, এটি সূচনা থেকে স্পষ্টভাবে ব্যাখ্যা করা হয়েছিল যে এটি কোথা থেকে আসতে পারে এবং আপনি একই সিদ্ধান্তে এসেছিলেন তা দেখে আমি আনন্দিত। এখন আপনার সূত্রটি দেখে, "দেখে মনে হচ্ছে ... আমি জানি না", আমি মনে করি এখানে একই পরিমাণের অনিশ্চয়তা রয়েছে, কারণ স্পষ্টতই আমি বা আপনি বুঝতে পারি না যে সংকলকটি কেন এই টেম্পটি তৈরি করতে হবে।
ক্রিস্টোফ

ঠিক আছে তারপরে আপনার উত্তরের সাথে সম্পর্কিত নয় এমন অংশগুলি সরিয়ে ফেলুন যা কেবলমাত্র একক সম্পর্কিত অনুচ্ছেদে পিছনে রয়েছে
লাইটনেস রেস

ঠিক আছে, আমি বিভ্রান্তকারী স্লাইসিং প্যারাটি সরিয়ে দিয়েছি এবং মানটির সুনির্দিষ্ট উল্লেখ সহ অনুলিপিটি সহ অনুলিপি করেছি।
ক্রিস্টোফ

আপনি ব্যাখ্যা করতে পারেন কেন একটি অস্থায়ী গাড়ি ট্যাক্সি থেকে অনুলিপি তৈরি করা উচিত এবং তারপরে আবার প্যারামিটারে অনুলিপি করা উচিত? এবং সরল গাড়ি সরবরাহ করার সময় সংকলক কেন এটি করে না?
ক্রিস্টোফ

3

কি হচ্ছে ?

আপনি যখন একটি তৈরি করেন Taxi, আপনি একটি Carসাবওবজেক্টও তৈরি করেন । এবং ট্যাক্সিটি ধ্বংস হয়ে গেলে, উভয় জিনিসই ধ্বংস হয়ে যায়। আপনি যখন ফোন করবেন তখন মানটি দিয়ে test()পাস করুন Car। সুতরাং দ্বিতীয়টি Carঅনুলিপি তৈরি হয় এবং যখন test()বাকী থাকে তখন ধ্বংস হয়ে যায়। সুতরাং আমাদের 3 টি ডিসস্ট্রাক্টরের ব্যাখ্যা রয়েছে: প্রথম এবং দু'টি ধারাবাহিকতায় শেষ।

চতুর্থ ডেস্ট্রাক্টর (এটি ক্রমের দ্বিতীয়টি) অপ্রত্যাশিত এবং আমি অন্য সংকলকগুলির সাথে পুনরুত্পাদন করতে পারিনি।

এটি যুক্তির Carউত্স হিসাবে কেবল অস্থায়ীভাবে তৈরি হতে Carপারে। যেহেতু Carযুক্তি হিসাবে সরাসরি কোনও মান সরবরাহ করার সময় এটি ঘটে না , তাই আমার সন্দেহ হয় এটি রূপান্তর করার Taxiজন্য Car। এটি অপ্রত্যাশিত, যেহেতু Carপ্রত্যেকটিতে ইতিমধ্যে একটি সাবোবজেক্ট রয়েছে Taxi। অতএব আমি মনে করি যে সংকলকটি একটি টেম্পে অপ্রয়োজনীয় রূপান্তর করে এবং অনুলিপিটি এড়াতে পারত এমন অনুলিপিটি এলিয়েন্সটি করে না।

মন্তব্যগুলিতে স্পষ্টতা দেওয়া:

আমার দাবিগুলি যাচাই করার জন্য ভাষা-আইনজীবীর মানক রেফারেন্স সহ এখানে স্পষ্টতা:

  • রূপান্তরটি আমি এখানে উল্লেখ করছি, এটি কনস্ট্রাক্টরের রূপান্তর [class.conv.ctor], অর্থাৎ অন্য শ্রেণীর (এখানে ট্যাক্সি) আর্গুমেন্টের ভিত্তিতে এক শ্রেণীর (এখানে গাড়ি) একটি অবজেক্ট তৈরি করা।
  • এই রূপান্তরটি এর Carমান ফেরত দেওয়ার জন্য একটি অস্থায়ী বস্তু ব্যবহার করে । এই সংকলকটির দ্বারা একটি অনুলিপি তৈরি করার অনুমতি দেওয়া হবে [class.copy.elision]/1.1, যেহেতু অস্থায়ী নির্মাণের পরিবর্তে এটি সরাসরি প্যারামিটারে ফিরে আসার মানটি তৈরি করতে পারে।
  • সুতরাং যদি এই টেম্পটি পার্শ্ব-প্রতিক্রিয়া দেয় তবে এটি কারণ কারণ সংকলক দৃশ্যত এই সম্ভাব্য অনুলিপিটি ব্যবহার করে না। এটি ভুল নয়, যেহেতু অনুলিপিটি অনুলিপি করা বাধ্যতামূলক নয়।

অ্যানাইসিসের পরীক্ষামূলক নিশ্চিতকরণ

আমি এখন একই সংকলকটি ব্যবহার করে আপনার কেস পুনরুত্পাদন করতে এবং যা চলছে তা নিশ্চিত করার জন্য একটি পরীক্ষা আঁকতে পারি।

উপরের আমার ধারণাটি ছিল যে সংকলকটি সাব-সাবটিক্যাল প্যারামিটার পাসিং প্রক্রিয়াটি নির্বাচন করেছে, Car(const &Taxi)এর Carসাবোবজেক্ট থেকে সরাসরি অনুলিপি নির্মাণের পরিবর্তে কনস্ট্রাক্টর রূপান্তর ব্যবহার করে Taxi

তাই আমি কলিং চেষ্টা test()কিন্তু স্পষ্টভাবে ভোটদান Taxiএকটি মধ্যে Car

আমার প্রথম প্রচেষ্টা পরিস্থিতি উন্নতি করতে সফল হয়নি। সংকলক এখনও suboptimal নির্মাণকারী রূপান্তর ব্যবহৃত:

test(static_cast<Car>(taxi));  // produces the same result with 4 destructor messages

আমার দ্বিতীয় প্রচেষ্টা সফল। এটি পাশাপাশি Caringালাইও করে তবে সংকলকটির সাবোবজেক্টটি ব্যবহার করার জন্য Taxiএবং এই নির্বোধ অস্থায়ী বস্তুটি তৈরি না করেই পয়েন্টার কাস্টিং ব্যবহার করে :

test(*static_cast<Car*>(&taxi));  //  :-)

এবং আশ্চর্য: এটি প্রত্যাশার মতো কাজ করে, কেবলমাত্র 3 টি ধ্বংসের বার্তাটি উত্পাদন করে :-)

সমাপ্তি পরীক্ষা:

একটি চূড়ান্ত পরীক্ষায়, আমি রূপান্তর দ্বারা একটি কাস্টম নির্মাণকারী সরবরাহ করেছি:

 class Car {
 ... 
     Car(const Taxi& t);  // not necessary but for experimental purpose
 }; 

এবং এটি দিয়ে বাস্তবায়ন *this = *static_cast<Car*>(&taxi);। নির্বোধ শোনায়, তবে এটি এমন কোড উত্পন্ন করে যা কেবলমাত্র 3 জন ডেস্ট্রাক্টর বার্তা প্রদর্শন করবে, এইভাবে অপ্রয়োজনীয় অস্থায়ী বস্তু এড়ানো হবে।

এটি এই ভাবনার দিকে পরিচালিত করে যে সংকলকটিতে কোনও বাগ থাকতে পারে যা এই আচরণের কারণ হয়ে দাঁড়ায়। এটি কিছুটা ক্ষেত্রে বেস ক্লাস থেকে সরাসরি অনুলিপি তৈরির সম্ভাবনা মিস করার সম্ভাবনা রয়েছে।


2
প্রশ্নের উত্তর দেয় না
লাইটনেস রেস ইন অরবিট

1
@ কিয়াজি আমার কাছে মনে হয় এটি অনুলিপি বিন্যাস ব্যতীত রূপান্তরকরণের জন্য অস্থায়ী অনুমানের সত্যতা নিশ্চিত করেছে, কারণ এই অস্থায়ীটি কলারের প্রসঙ্গে, ফাংশন থেকে বের হয়ে আসবে।
ক্রিস্টোফ

1
যখন "আপনার সংকলক কপি এলিজেন না করে ট্যাক্সি থেকে গাড়ীতে রূপান্তর" বলার সময়, আপনি কোন অনুলিপিটি উল্লেখ করছেন? এমন কোনও অনুলিপি থাকা উচিত যা প্রথমে এলিটেড হওয়া দরকার।
ইন্টারজয়

1
@ ইনটারজয় কারণ সংকলকটিকে ট্যাক্সিের কার সাব-অবজেক্টের উপর ভিত্তি করে রূপান্তর করার জন্য কোনও গাড়ি অস্থায়ী নির্মাণ করার প্রয়োজন নেই এবং তারপরে এই টেম্পটিকে কার প্যারামিটারে অনুলিপি করতে হবে: এটি অনুলিপিটি সহ্য করতে পারে এবং মূল সাবোবজেক্ট থেকে সরাসরি প্যারামিটারটি তৈরি করতে পারে।
ক্রিস্টোফ

1
অনুলিপিটি হ'ল যখন স্ট্যান্ডার্ডটি বলে যে একটি অনুলিপি তৈরি করা উচিত, তবে নির্দিষ্ট পরিস্থিতিতে কপিটি অনুকরণের অনুমতি দেয়। এক্ষেত্রে প্রথমে কোনও অনুলিপি তৈরি করার কোনও কারণ নেই ( Taxiসরাসরি একটি Carঅনুলিপি অনুলিপি নির্মাণকারীকে দেওয়া যেতে পারে ), সুতরাং অনুলিপিটি অনুলিপিযোগ্য।
ইন্টারজয়
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.