এই নির্দিষ্ট ক্ষেত্রে, কোনও সদস্য ইনিশিয়ালাইজার তালিকা ব্যবহার করে এবং কনস্ট্রাক্টরে মান নির্ধারণের মধ্যে কি পার্থক্য রয়েছে?


90

অভ্যন্তরীণভাবে এবং উত্পন্ন কোড সম্পর্কে, এর মধ্যে কি সত্যিই পার্থক্য রয়েছে:

MyClass::MyClass(): _capacity(15), _data(NULL), _len(0)
{
}

এবং

MyClass::MyClass()
{
  _capacity=15;
  _data=NULL;
  _len=0
}

ধন্যবাদ ...

উত্তর:


61

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


17
রিচার্ড বলেছিলেন, এই মানগুলি যদি আদিম ধরণের এবং কনস্ট হয় তবে এটি কোনও তাত্পর্যপূর্ণ হবে, সূচনা তালিকার সদস্যদের মান নির্ধারণের একমাত্র উপায়।
thbusch

11
এটি কেবল তখন বর্ণিত হিসাবে কাজ করে যখন ভেরিয়েবলগুলি রেফারেন্স বা ধ্রুবক না হয়, যদি তারা হয় ধ্রুব বা রেফারেন্স হয় তবে এটি সূচনা তালিকা ব্যবহার না করে সংকলনও করবে না।
স্টিফানবি

77

ধ্রুবক সদস্য, রেফারেন্স এবং বেস ক্লাস আরম্ভ করার জন্য আপনার সূচনা তালিকাটি ব্যবহার করতে হবে

যখন আপনাকে ধ্রুবক সদস্য, রেফারেন্স এবং বেস ক্লাস কনস্ট্রাক্টরগুলিকে পরামিতিগুলি পাস করার দরকার হয়, যেমন মন্তব্যগুলিতে উল্লিখিত হয়েছে, আপনাকে আরম্ভের তালিকাটি ব্যবহার করতে হবে।

struct aa
{
    int i;
    const int ci;       // constant member

    aa() : i(0) {} // will fail, constant member not initialized
};

struct aa
{
    int i;
    const int ci;

    aa() : i(0) { ci = 3;} // will fail, ci is constant
};

struct aa
{
    int i;
    const int ci;

    aa() : i(0), ci(3) {} // works
};

উদাহরণ (সম্পূর্ণ নয়) শ্রেণি / কাঠামোর উল্লেখ রয়েছে:

struct bb {};

struct aa
{
    bb& rb;
    aa(bb& b ) : rb(b) {}
};

// usage:

bb b;
aa a(b);

এবং বেস শ্রেণীর সূচনা করার উদাহরণ যার জন্য প্যারামিটার প্রয়োজন (উদাহরণস্বরূপ কোনও ডিফল্ট নির্মাণকারী নেই):

struct bb {};

struct dd
{
    char c;
    dd(char x) : c(x) {}
};

struct aa : dd
{
    bb& rb;
    aa(bb& b ) : dd('a'), rb(b) {}
};

4
এবং যদি _capacity, _dataএবং _lenঅ্যাক্সেসযোগ্য ডিফল্ট নির্মাণকারী ছাড়া ক্লাসের ধরণ রয়েছে?
সিবি বেইলি

4
আপনি যে কনস্ট্রাক্টর উপলভ্য তা কল করুন, যদি আপনাকে আরও মান নির্ধারণ করতে হয় তবে আপনি তাদের আপনার নির্মাণকারীর শরীর থেকে কল করুন। এখানে পার্থক্যটি হ'ল আপনি constকন্সট্রাক্টরের শরীরে সদস্যকে আরম্ভ করতে পারবেন না , আপনাকে আরম্ভের তালিকাটি ব্যবহার constকরতে হবে - অ- সদস্যদের সূচনা তালিকায় বা কনস্ট্রাক্টরের মূল অংশে আরম্ভ করা যেতে পারে।
স্টিফানবি

@ স্টেফান: আপনি কনস্ট্রাক্টরকে কল করতে পারবেন না। কোন ডিফল্ট কনস্ট্রাক্টরবিহীন একটি ক্লাসকে কনস্টের সদস্যদের মতো ইনিশিয়ালাইজার তালিকায় ইনিশিয়াল করতে হয়।
GManNickG


4
@ স্টেফানবি: আমার ক্ষমাপ্রার্থী যদি আমি বুঝিয়ে দিয়েছি যে আপনি যখন বাস্তবে করবেন তখন আপনি এটি বুঝতে পারবেন না। আপনার উত্তরে আপনি কেবল তখনই বলেছিলেন যখন কোনও বেস বা সদস্যের নাম শুরুতে তালিকার তালিকায় রাখতে হবে, আপনি ব্যাখ্যা করেননি যে আরম্ভকারী-তালিকার সূচনা এবং কনস্ট্রাক্টর বডিতে কার্যনির্বাহী করার মধ্যে ধারণাগত পার্থক্য আসলে এটিই যেখানে আমার ভুল বোঝাবুঝি থেকে আসতে পারে।
সিবি বেইলি

18

হ্যাঁ. প্রথম যদি আপনি ডিক্লেয়ার করতে পারেন _capacity, _dataএবং _lenধ্রুবক হিসাবে:

class MyClass
{
private:
    const int _capacity;
    const void *_data;
    const int _len;
// ...
};

এটি গুরুত্বপূর্ণ হবে যদি আপনি constরানটাইমের সময় এই উদাহরণগুলির পরিবর্তনশীলগুলির মানগুলি গণনা করার সময় নিশ্চিত করতে চান , উদাহরণস্বরূপ:

MyClass::MyClass() :
    _capacity(someMethod()),
    _data(someOtherMethod()),
    _len(yetAnotherMethod())
{
}

constদৃষ্টান্তগুলি অবশ্যই আরম্ভকারী তালিকায় শুরু করতে হবে বা অন্তর্নিহিত প্রকারগুলি অবশ্যই সর্বজনীন পরামিতি বিহীন নির্মাতাদের সরবরাহ করতে হবে (যা আদিম ধরণেরগুলি করে)।


4
একই রেফারেন্স জন্য যায়। যদি আপনার শ্রেণিতে রেফারেন্স সদস্য থাকে তবে তাদের অবশ্যই প্রাথমিকের তালিকায় প্রাথমিক করা উচিত
মার্ক রান্সম

7

আমি মনে করি এই লিঙ্কটি http://www.cplusplus.com/forum/articles/17820/ একটি দুর্দান্ত ব্যাখ্যা দেয় - বিশেষত সি ++ তে নতুন যারা।

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

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


5

আমি যুক্ত করব যে আপনার যদি ক্লাস ধরণের সদস্য নেই তবে কোনও ডিফল্ট কনস্ট্রাক্টর উপলব্ধ নেই, আপনার ক্লাসটি তৈরির একমাত্র উপায় ইনিশিয়ালাইজেশন।


3

একটি বড় পার্থক্য হ'ল এই নিয়োগটি পিতামাতার শ্রেণীর সদস্যদের সূচনা করতে পারে; ইনিশিয়ালাইজার কেবলমাত্র বর্তমান শ্রেণীর স্কোপে ঘোষিত সদস্যদের উপর কাজ করে।


2

জড়িত ধরণের উপর নির্ভর করে। পার্থক্যও এর মধ্যে একই রকম

std::string a;
a = "hai";

এবং

std::string a("hai");

যেখানে দ্বিতীয় ফর্মটি ইনিশিয়েশন লিস্ট - এটি হ'ল এটির পার্থক্য রয়েছে যদি টাইপটিতে কনস্ট্রাক্টর আর্গুমেন্টের প্রয়োজন হয় বা কনস্ট্রাক্টর আর্গুমেন্টগুলির সাথে আরও দক্ষ হয়।


1

আসল পার্থক্যটি কীভাবে জিসিসি সংকলক মেশিন কোড জেনারেট করে এবং মেমরিটি রাখে তা নিয়ে ফোটে। ব্যাখ্যা করা:

  • (ফেজ 1) টি এনডি বডিটির আগে (আরআইডি তালিকা সহ): সংকলক শ্রেণীর জন্য প্রয়োজনীয় মেমরি বরাদ্দ করে। ক্লাসটি ইতিমধ্যে বেঁচে আছে!
  • (ফেজ ২) ইন ডি বডিতে: যেহেতু মেমরি বরাদ্দ করা হয়, তাই এখন প্রতিটি অ্যাসাইনমেন্ট ইতিমধ্যে উপস্থিত / 'ইনিশিয়ালাইজড' ভেরিয়েবলের একটি ক্রিয়াকলাপ নির্দেশ করে।

কনস্টের ধরণের সদস্যদের পরিচালনা করার অবশ্যই অন্যান্য উপায় রয়েছে। তবে তাদের জীবনকে স্বাচ্ছন্দ্য করতে, জিসিসি সংকলক লেখকরা কিছু বিধি সেট আপ করার সিদ্ধান্ত নেন

  1. কনস্ট টাইপ সদস্যদের ডিআইডি বডিের আগে অবশ্যই আরম্ভ করা উচিত।
  2. ফেজ 1 এর পরে, যে কোনও রাইটিং অপারেশন কেবল অ স্থির সদস্যদের জন্য বৈধ।

1

আরম্ভ করার একমাত্র উপায় আছেবেস শ্রেণীর উদাহরণগুলি এবং অ-স্থিতিশীল সদস্য ভেরিয়েবলগুলি এবং তা হ'ল আরম্ভকারী তালিকাটি ব্যবহার করা।

আপনি যদি আপনার নির্মাণকারীর প্রাথমিক তালিকায় কোনও বেস বা অ-স্থিতিশীল সদস্যের পরিবর্তনশীল নির্দিষ্ট না করে থাকেন তবে সেই সদস্য বা বেসটি ডিফল্ট-আরম্ভ হবে (সদস্য / বেস যদি নন-পিওড শ্রেণীর ধরণ বা নন-পিওডি শ্রেণীর অ্যারে হয় তবে প্রকারভেদ) বা অন্যথায় অবিচ্ছিন্ন বাম।

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

আপনি কনস্ট্রাক্টর বডিতে সদস্যদের জন্য নতুন মান নির্ধারণ করতে সক্ষম হতে পারেন তবে এটি নির্ধারণ করা সম্ভব নয় is const সদস্যদের বা অ- হয়েছে এবং রেফারেন্সগুলি পুনরায় প্রত্যাবর্তন করা সম্ভব নয় এমন শ্রেণীর সদস্য বা সদস্যদের সম্ভব নয়।

প্রকারভেদে নির্মিত এবং কিছু ব্যবহারকারী-সংজ্ঞায়িত প্রকারের জন্য, কনস্ট্রাক্টর বডিতে নির্ধারণের ক্ষেত্রে ইনিশিয়ালার তালিকার একই মান দিয়ে আরম্ভ করার মতো একই প্রভাব থাকতে পারে।

আপনি যদি কোনও প্রাথমিক বা তালিকার কোনও সদস্য বা বেসের নাম দিতে ব্যর্থ হন এবং সেই সত্তাটি একটি রেফারেন্স হয়, কোনও ক্লাসের ধরণ নেই যার দ্বারা অ্যাক্সেসযোগ্য ব্যবহারকারী-ঘোষিত ডিফল্ট কনস্ট্রাক্টর নেই, constযোগ্য এবং পিওড টাইপ বা পিওড শ্রেণির ধরণ বা পিওড শ্রেণির ধরণের অ্যারে একজন constযোগ্যতাসম্পন্ন সদস্য সমন্বিত (প্রত্যক্ষ বা পরোক্ষভাবে) এর পরে প্রোগ্রামটি দুর্গঠিত।


0

আপনি যদি একটি প্রাথমিক তালিকার তালিকা লিখেন, আপনি সমস্ত এক ধাপে করেন; আপনি যদি কোনও ইনিমিলাইজার তালিকাটি না লিখে থাকেন তবে আপনি 2 টি পদক্ষেপ করবেন: একটি ঘোষণার জন্য এবং একটিতে মানটি স্বাক্ষর করার জন্য।


0

কনস্ট্রাক্টরে ইনিশিয়ালাইজেশন তালিকা এবং ইনিশিয়ালাইজেশন স্টেটমেন্টের মধ্যে পার্থক্য রয়েছে। কোড নীচে বিবেচনা করা যাক:

#include <initializer_list>
#include <iostream>
#include <algorithm>
#include <numeric>

class MyBase {
public:
    MyBase() {
        std::cout << __FUNCTION__ << std::endl;
    }
};

class MyClass : public MyBase {
public:
    MyClass::MyClass() : _capacity( 15 ), _data( NULL ), _len( 0 ) {
        std::cout << __FUNCTION__ << std::endl;
    }
private:
    int _capacity;
    int* _data;
    int _len;
};

class MyClass2 : public MyBase {
public:
    MyClass2::MyClass2() {
        std::cout << __FUNCTION__ << std::endl;
        _capacity = 15;
        _data = NULL;
        _len = 0;
    }
private:
    int _capacity;
    int* _data;
    int _len;
};

int main() {
    MyClass c;
    MyClass2 d;

    return 0;
}

যখন মাইক্লাস ব্যবহার করা হবে তখন নির্বাহকের প্রথম বিবৃতি কার্যকর করার আগে সমস্ত সদস্যকে আরম্ভ করা হবে।

কিন্তু, যখন মাইক্লাস 2 ব্যবহার করা হয়, যখন কোনও কনস্ট্রাক্টরের প্রথম বিবৃতি কার্যকর করা হয় তখন সমস্ত সদস্য আরম্ভ হয় না।

পরে ক্ষেত্রে, নির্দিষ্ট সদস্যের সূচনা করার আগে কেউ যদি কোনও কনস্ট্রাক্টরে কিছু কোড যুক্ত করে তখন রিগ্রেশন সমস্যা হতে পারে।


0

এখানে এমন একটি বিষয় যা আমি অন্যকে এটি উল্লেখ করতে দেখিনি:

class temp{
public:
   temp(int var);
};

টেম্প ক্লাসে একটি ডিফল্ট কর্টর নেই। যখন আমরা এটি অন্য শ্রেণিতে নিম্নলিখিত হিসাবে ব্যবহার করি:

class mainClass{
public:
 mainClass(){}
private:
  int a;
  temp obj;
};

কোডটি সংকলন করবে না, কারণ objসংকলকটি কীভাবে আরম্ভ করতে হবে তা জানে না , কারণ এটির মধ্যে কেবল একটি স্পষ্ট স্পষ্ট বর্ণ রয়েছে যা কোনও মান অর্জন করে, সুতরাং আমাদের নিম্নলিখিত হিসাবে নিম্নলিখিতটি পরিবর্তন করতে হবে:

mainClass(int sth):obj(sth){}

সুতরাং, এটি কেবল কনস্ট এবং রেফারেন্সগুলিই নয়!

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.