c++ tutorial কিভাবে "= ডিফল্ট" ডিফল্ট কন্সট্রকটার এবং ধ্বংসকারীর জন্য "{}" থেকে ভিন্ন?




the c++ programming language (3)

মধ্যে গুরুত্বপূর্ণ পার্থক্য

class B {
    public:
    B(){}
    int i;
    int j;
};

এবং

class B {
    public:
    B() = default;
    int i;
    int j;
};

ডিফল্ট কন্সট্রাকটর B() = default; দিয়ে সংজ্ঞায়িত করা হয় B() = default; বলা হয় না ব্যবহারকারীর সংজ্ঞা । এর মানে হল মান-প্রবর্তনের ক্ষেত্রে

B* pb = new B();  // use of () triggers value-initialization

বিশেষ ধরনের প্রারম্ভিক যেটি কোনও কনস্ট্রাক্টার ব্যবহার করে না সেটি সংঘটিত হবে এবং বিল্ট-ইন প্রকারের জন্য এটি শূন্য-ইনিশিয়ালাইজেশন হিসাবে কার্যকর হবেB(){} ক্ষেত্রে B(){} এটি হবে না। সি ++ স্ট্যান্ডার্ড n3337 § 8.5 / 7 বলে

টাইপের একটি বস্তুর মূল্য-প্রাথমিককরণ করার অর্থ হল:

- যদি টি ব্যবহারকারীর প্রদত্ত কনস্ট্রাক্টর (12.1) সহ একটি (সম্ভবত সিভি-যোগ্য) শ্রেণির ধরন (ক্লজ 9) হয় তবে T এর জন্য ডিফল্ট কনস্ট্রাক্টর বলা হয় (এবং টিটি যদি অ্যাক্সেসযোগ্য ডিফল্ট কন্সট্রকটার না থাকে তবে প্রাথমিকভাবে দুর্নীতি হয় );

- যদি T একটি (সম্ভবত সিভি-যোগ্য) কোনও ব্যবহারকারী-সরবরাহকৃত কনস্ট্রাক্টর ছাড়াই অ-ইউনিয়ন শ্রেণির ধরন থাকে, তবে বস্তুটি শূন্য-ইনিশিয়ালাইজড এবং যদি T এর নিখুঁতভাবে-ঘোষণা করা ডিফল্ট কন্সট্রাক্টর অ-তুচ্ছ হয়, তবে সেই কন্সট্রাকটরকে বলা হয়।

- যদি টি একটি অ্যারে টাইপ হয়, তবে প্রতিটি উপাদান মান-প্রাথমিক হয়; - অন্যথায়, বস্তু শূন্য-প্রাথমিক হয়।

উদাহরণ স্বরূপ:

#include <iostream>

class A {
    public:
    A(){}
    int i;
    int j;
};

class B {
    public:
    B() = default;
    int i;
    int j;
};

int main()
{
    for( int i = 0; i < 100; ++i) {
        A* pa = new A();
        B* pb = new B();
        std::cout << pa->i << "," << pa->j << std::endl;
        std::cout << pb->i << "," << pb->j << std::endl;
        delete pa;
        delete pb;
    }
  return 0;
}

সম্ভাব্য ফলাফল:

0,0
0,0
145084416,0
0,0
145084432,0
0,0
145084416,0
//...

http://ideone.com/k8mBrd

আমি মূলত এটি শুধুমাত্র ধ্বংসকারী সম্পর্কে প্রশ্ন হিসাবে পোস্ট করেছি, তবে এখন আমি ডিফল্ট কনস্ট্রাকটরটির বিবেচনা যোগ করছি। এখানে মূল প্রশ্ন:

যদি আমি আমার ক্লাসকে ভার্চুয়াল ভাস্কর্য দিতে চাই, তবে অন্যথায় কম্পাইলার যা জেনারেট করবে তা একই রকম, আমি =default ব্যবহার করতে পারি:

class Widget {
public:
   virtual ~Widget() = default;
};

কিন্তু মনে হচ্ছে আমি খালি সংজ্ঞা ব্যবহার করে কম টাইপ করে একই প্রভাব পেতে পারি:

class Widget {
public:
   virtual ~Widget() {}
};

এই দুটি সংজ্ঞা ভিন্নভাবে আচরণ করে এমন কোন উপায় আছে কি?

এই প্রশ্নটির জন্য পোস্ট করা জবাবগুলির উপর ভিত্তি করে, ডিফল্ট কন্সট্রকটরের পরিস্থিতি একই রকম মনে হয়। ডিস্ট্রাক্টরদের জন্য " =default " এবং " {} " এর মধ্যে অর্থের মধ্যে কোন পার্থক্য নেই, তাই ডিফল্ট কন্সট্রকটারগুলির জন্য এই বিকল্পগুলির মধ্যে অর্থের মধ্যে কোনও পার্থক্য নেই? অর্থাৎ, আমি এমন একটি ধরন তৈরি করতে চাই যেখানে সেই ধরনের বস্তু তৈরি এবং ধ্বংস করা হবে, কেন আমি বলতে চাই

Widget() = default;

পরিবর্তে

Widget() {}

?

মূল পোস্টিংয়ের পরে এই প্রশ্নটি বাড়িয়ে যদি কিছু SO নিয়ম লঙ্ঘন করে তবে আমি ক্ষমাপ্রার্থী। ডিফল্ট কন্সট্রকটরগুলির জন্য প্রায় একই রকমের প্রশ্ন পোস্ট করা আমাকে কম পছন্দসই বিকল্প হিসাবে মারধর করে।


তারা উভয় অ-তুচ্ছ।

তারা উভয় বেস এবং সদস্যদের নিখরচায় স্পেসিফিকেশন উপর নির্ভর করে একই nonexcept স্পেসিফিকেশন আছে।

আমি যতদূর সনাক্ত করছি শুধুমাত্র পার্থক্যটি হল যে যদি Widget কোনও অ্যাক্সেসযোগ্য বা মুছে ফেলা বিধ্বংসী কোন বেস বা সদস্য থাকে তবে:

struct A
{
private:
    ~A();
};

class Widget {
    A a_;
public:
#if 1
   virtual ~Widget() = default;
#else
   virtual ~Widget() {}
#endif
};

তারপর =default সমাধান কম্পাইল হবে, কিন্তু Widget একটি ধ্বংসাত্মক টাইপ হবে না। যদি আপনি একটি Widget ধ্বংস করার চেষ্টা করেন তবে আপনি একটি কম্পাইল-টাইম ত্রুটি পাবেন। কিন্তু আপনি যদি না করেন, আপনি একটি কর্মসূচী পেয়েছেন।

ওহ, আপনি যদি ব্যবহারকারী সরবরাহকৃত বিধ্বংসী সরবরাহকারী সরবরাহ করেন, তবে আপনি কোনও Widget ধ্বংস করবেন কিনা তা সংকলন করবে না:

test.cpp:8:7: error: field of type 'A' has private destructor
    A a_;
      ^
test.cpp:4:5: note: declared private here
    ~A();
    ^
1 error generated.

ধ্বংসকারীদের চেয়ে কন্সট্রকটার সম্পর্কে জিজ্ঞাসা করার সময় এটি একটি সম্পূর্ণ ভিন্ন প্রশ্ন।

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

বিশেষ সদস্য ফাংশন (ডিফল্ট কন্সট্রাকটর, অনুলিপি / সরানো কনস্ট্রাক্টর / অ্যাসাইনমেন্ট, ধ্বংসকারী ইত্যাদি) = default সিনট্যাক্স ব্যবহার করে কেবল {} । পরেরটির সাথে, ফাংশনটি "ব্যবহারকারী সরবরাহকৃত" হয়ে ওঠে। এবং যে সবকিছু পরিবর্তন।

এটি সি ++ 11 এর সংজ্ঞা দ্বারা একটি তুচ্ছ শ্রেণী:

struct Trivial
{
  int foo;
};

আপনি যদি ডিফল্ট গঠনটি করার চেষ্টা করেন তবে কম্পাইলারটি স্বয়ংক্রিয়ভাবে একটি ডিফল্ট কন্সট্রকটার তৈরি করবে। একই কপি / আন্দোলন এবং ধ্বংস করার জন্য যায়। যেহেতু ব্যবহারকারী এই সদস্য ফাংশনগুলির কোনও প্রদান করে নি, C ++ 11 স্পেসিফিকেশনটি এটি একটি "তুচ্ছ" বর্গকে বিবেচনা করে। সুতরাং এটি এমপিসিপির মত তাদের বিষয়বস্তুগুলিকে তাদের প্রাথমিকভাবে শুরু করতে এবং এটিকে আরও এগিয়ে নিয়ে যাওয়ার মতো আইনি কাজ করে।

এই:

struct NotTrivial
{
  int foo;

  NotTrivial() {}
};

নাম প্রস্তাব হিসাবে, এই আর তুচ্ছ হয়। এটি একটি ডিফল্ট কনস্ট্রাক্টর যা ব্যবহারকারী-সরবরাহকৃত। এটা খালি যদি এটা কোন ব্যাপার না; যতক্ষন পর্যন্ত সি ++ 11 এর নিয়মগুলি উদ্বিগ্ন হয়, এটি একটি তুচ্ছ টাইপ হতে পারে না।

এই:

struct Trivial2
{
  int foo;

  Trivial2() = default;
};

নাম হিসাবে আবার প্রস্তাব, এই একটি তুচ্ছ টাইপ। কেন? ডিফল্ট কন্সট্রাকটর স্বয়ংক্রিয়ভাবে জেনারেট করার জন্য আপনি কম্পাইলারকে বলেছিলেন। কনস্ট্রাক্টর তাই "ব্যবহারকারী দ্বারা সরবরাহ করা হয় না।" এবং তাই, টাইপটি তুচ্ছ হিসাবে গণনা করে, কারণ এতে ব্যবহারকারী-সরবরাহকৃত ডিফল্ট কনস্ট্রাক্টর নেই।

= default সিনট্যাক্স মূলত কন্সট্রাক্টর / অ্যাসাইনমেন্টের মত কাজ করার জন্য সেখানে থাকে, যখন আপনি এমন ফাংশন তৈরি করতে বাধা দেয় এমন সদস্য ফাংশন যোগ করেন। কিন্তু এটি কম্পাইলার থেকে বিশেষ আচরণকেও ট্রিগার করে, তাই এটি ডিফল্ট কনস্ট্রাক্টর / ধ্বংসকারীগুলিতেও উপকারী।







deleted-functions