তালিকার প্রাথমিককরণ (কোঁকড়ানো ধনুর্বন্ধনী ব্যবহার করে) বিকল্পগুলির চেয়ে ভাল কেন?


405
MyClass a1 {a};     // clearer and less error-prone than the other three
MyClass a2 = {a};
MyClass a3 = a;
MyClass a4(a);

কেন?

আমি এসও-তে কোনও উত্তর খুঁজে পাইনি, সুতরাং আমাকে আমার নিজের প্রশ্নের উত্তর দিন।


12
কেন ব্যবহার autoকরবেন না ?
মার্ক গার্সিয়া

33
এটি সত্য, এটি সুবিধাজনক, তবে এটি আমার মতে পঠনযোগ্যতা হ্রাস করে - আমি কোড পড়ার সময় কোনও অবজেক্টটি কী ধরণের তা দেখতে পছন্দ করি । আপনি যদি 100% নিশ্চিত হন তবে কী কী জিনিসটি টাইপ হয় তা অটো কেন ব্যবহার করবেন? এবং আপনি যদি তালিকা সূচনাটি ব্যবহার করেন (আমার উত্তরটি পড়ুন), আপনি নিশ্চিত হতে পারেন যে এটি সর্বদা সঠিক।
ওলেকসই

102
@ ওলেকসী: std::map<std::string, std::vector<std::string>>::const_iteratorআপনার সাথে একটি শব্দ চাই।
জিও

9
@ ওলেকসী আমি এই গটডাব্লু পড়ার পরামর্শ দিচ্ছি
Rapptz

17
@ ডক আমি বলছি using MyContainer = std::map<std::string, std::vector<std::string>>;আরও ভাল (বিশেষত আপনি এটি টেমপ্লেট করতে পারেন!)
জ্যাব

উত্তর:


356

মূলত বার্জন স্ট্রস্ট্রপের "দ্য সি ++ প্রোগ্রামিং ল্যাঙ্গুয়েজ ৪ র্থ সংস্করণ" থেকে অনুলিপি এবং আটকানো :

তালিকা সূচনা সংকীর্ণ করার অনুমতি দেয় না (আইসো .8.5.4)। এটাই:

  • একটি পূর্ণসংখ্যা অন্য পূর্ণসংখ্যায় রূপান্তর করা যায় না যা এর মান ধরে রাখতে পারে না। উদাহরণস্বরূপ, চর থেকে ইন করার অনুমতি দেওয়া হয়েছে তবে চরের সাথে ইন্টার নয়।
  • একটি ভাসমান-পয়েন্ট মানকে অন্য ভাসমান-বিন্দু ধরণের রূপান্তর করা যায় না যা এর মান ধরে রাখতে পারে না। উদাহরণস্বরূপ, ভাসা থেকে দ্বিগুণ অনুমোদিত, তবে ভাসা থেকে দ্বিগুণ নয়।
  • একটি ভাসমান-পয়েন্ট মানকে একটি পূর্ণসংখ্যার ধরণে রূপান্তর করা যায় না।
  • একটি পূর্ণসংখ্যা মান ভাসমান-বিন্দুর ধরণে রূপান্তর করা যায় না।

উদাহরণ:

void fun(double val, int val2) {

    int x2 = val; // if val==7.9, x2 becomes 7 (bad)

    char c2 = val2; // if val2==1025, c2 becomes 1 (bad)

    int x3 {val}; // error: possible truncation (good)

    char c3 {val2}; // error: possible narrowing (good)

    char c4 {24}; // OK: 24 can be represented exactly as a char (good)

    char c5 {264}; // error (assuming 8-bit chars): 264 cannot be 
                   // represented as a char (good)

    int x4 {2.0}; // error: no double to int value conversion (good)

}

শুধুমাত্র অবস্থা যেখানে = ওভার পছন্দ করা হয় {} যখন ব্যবহার করছে autoশব্দ টাইপ সূচনাকারী দ্বারা নির্ধারিত জন্য।

উদাহরণ:

auto z1 {99};   // z1 is an int
auto z2 = {99}; // z2 is std::initializer_list<int>
auto z3 = 99;   // z3 is an int

উপসংহার

আপনার না করার দৃ strong় কারণ না থাকলে বিকল্পগুলির চেয়ে {} সূচনাটিকে অগ্রাধিকার দিন।


52
এটি ()একটি ফাংশন ঘোষণা হিসাবে পার্স করা যেতে পারে যে সত্য আছে । এটি বিভ্রান্তিকর এবং বেমানান যা আপনি বলতে পারেন T t(x,y,z);তবে না T t()। এবং কখনও কখনও, আপনি নিশ্চিত x, আপনি এমনকি বলতে পারেন না T t(x);
জুয়ানচোপাঞ্জা

84
আমি এই উত্তরটির সাথে দৃ strongly়ভাবে একমত নই; যখন আপনার কোনও কন্ট্রোর গ্রহণের সাথে টাইপ থাকে তখন ব্রেসড ইনিশিয়ালাইজেশন সম্পূর্ণ গণ্ডগোল হয়ে যায় std::initializer_list। রেডএক্সআইআইআই এই সমস্যাটির উল্লেখ করেছে (এবং কেবল এটি ব্রাশ করে), যেখানে আপনি এটি সম্পূর্ণ উপেক্ষা করেন। A(5,4)এবং A{5,4}সম্পূর্ণ ভিন্ন ফাংশন কল করতে পারে, এবং এটি জানা গুরুত্বপূর্ণ বিষয়। এমনকি এমন কলগুলির ফলাফল হতে পারে যা অপ্রয়োজনীয় বলে মনে হয়। আপনার {}ডিফল্টরূপে পছন্দ করা উচিত তা বলার ফলে লোকেরা কী হচ্ছে তা ভুল বুঝাবুঝির দিকে পরিচালিত করবে। যদিও এটি আপনার দোষ নয়। আমি ব্যক্তিগতভাবে মনে করি এটি একটি অত্যন্ত দুর্বল চিন্তার বৈশিষ্ট্য।
ব্যবহারকারী 1520427

13
@ ব্যবহারকারী1520427 এ কারণেই " যদি আপনার কাছে অংশ না নেওয়ার দৃ strong় কারণ না থাকে তবে " রয়েছে।
ওলেকসই

67
যদিও এই প্রশ্নটি পুরানো এটি বেশ কয়েকটি হিট হয়েছে আমি কেবল এখানে রেফারেন্সের জন্য এটি যুক্ত করছি (আমি এটি পৃষ্ঠায় অন্য কোথাও দেখিনি)। ব্রেসড-থ্রি-তালিকা থেকে অটো কমানোর জন্য নতুন বিধিগুলি সহ সি ++ 14 থেকে এখন auto var{ 5 }এটি লেখা সম্ভব এবং এটি intআর ছাড়াই হবে না std::initializer_list<int>
এডোয়ার্ডো স্পারকন ডোমিনিসি

12
হাহা, সমস্ত মন্তব্য থেকে এটি এখনও কি করা উচিত তা পরিষ্কার নয়। স্পষ্টত কি, সি ++ স্পেসিফিকেশন একটি গোলযোগ!
ড্রামম

113

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

  • যদি আমি অবজেক্টটি তৈরি করছি যা আমি কনস্ট্রাক্টরের (যেমন পাত্রে, পিওডি স্ট্রোকস, অ্যাটমিক্স, স্মার্ট পয়েন্টার ইত্যাদি) পাস করছি তার মানগুলি ধারণ করে, তবে আমি বন্ধনীগুলি ব্যবহার করছি।
  • যদি কনস্ট্রাক্টর কোনও সাধারণ ফাংশন কলের অনুরূপ হয় (এটি কিছু বা কম জটিল ক্রিয়াকলাপগুলি সম্পাদন করে যা আর্গুমেন্টগুলির মাধ্যমে প্যারামেট্রাইজড হয়) তবে আমি সাধারণ ফাংশন কল সিনট্যাক্স ব্যবহার করছি।
  • ডিফল্ট সূচনা করার জন্য আমি সর্বদা কোঁকড়ানো ধনুর্বন্ধনী ব্যবহার করি।
    একটির জন্য, আমি সর্বদা নিশ্চিত যে অবজেক্টটি প্রাথমিকভাবে কোনও ডিফল্ট কনস্ট্রাক্টর সহ একটি "সত্য" শ্রেণি কিনা তা যেমন নির্বিশেষে বা একটি বিল্টিন / পিওডি টাইপ হবে তা নির্বিশেষে প্রারম্ভিক হয়ে ওঠে sure দ্বিতীয়টি হ'ল - বেশিরভাগ ক্ষেত্রে - প্রথম নিয়মের সাথে সামঞ্জস্যপূর্ণ, কোনও ডিফল্ট আরম্ভিকৃত অবজেক্ট প্রায়শই একটি "খালি" বস্তুর প্রতিনিধিত্ব করে।

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

এটি উদাহরণস্বরূপ স্ট্যান্ডার্ড লাইব্রেরি-ধরণের সাথে পুরোপুরি ফিট করে std::vector:

vector<int> a{10,20};   //Curly braces -> fills the vector with the arguments

vector<int> b(10,20);   //Parentheses -> uses arguments to parametrize some functionality,                          
vector<int> c(it1,it2); //like filling the vector with 10 integers or copying a range.

vector<int> d{};      //empty braces -> default constructs vector, which is equivalent
                      //to a vector that is filled with zero elements

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

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

4
বেশ পরিষ্কার নিয়মকানুন।
লাইক

5
এটি এখন পর্যন্ত সেরা উত্তর। } inherit উত্তরাধিকারের মতো - অপব্যবহারের পক্ষে সহজ, কোড বোঝার পক্ষে কঠিন।
ইউকেমনকি

2
@ মাইকএমবি উদাহরণ: const int &b{}<- একটি অবিশ্বাস্য রেফারেন্স তৈরি করার চেষ্টা করে না, তবে এটি একটি অস্থায়ী পূর্ণসংখ্যার বস্তুকে আবদ্ধ করে। দ্বিতীয় উদাহরণ: struct A { const int &b; A():b{} {} };<- একটি অবিশ্বাস্য রেফারেন্স তৈরি করার চেষ্টা ()করবেন না (যেমনটি হবে), তবে এটি একটি অস্থায়ী পূর্ণসংখ্যার বস্তুর সাথে আবদ্ধ করুন এবং তারপরে এটি জটলা ছেড়ে দিন। এমনকি জিসিসি -Wallদ্বিতীয় উদাহরণের জন্য সতর্ক করে না।
জোহানেস স্কাউব -

91

সেখানে ব্যবহার বক্রবন্ধনী আরম্ভের অনেক কারণ আছে, কিন্তু আপনি সচেতন হওয়া উচিত যে কন্সট্রাকটর অন্যান্য কনস্ট্রাকটর পছন্দের , ব্যতিক্রম ডিফল্ট-কন্সট্রাকটর হচ্ছে। এটি কনস্ট্রাক্টর এবং টেমপ্লেটগুলির সাথে সমস্যার দিকে পরিচালিত করে যেখানে টাইপ কনস্ট্রাক্টর হয় আরম্ভকারী তালিকার তালিকা বা একটি সরল পুরানো কর্টর হতে পারে।initializer_list<>T

struct Foo {
    Foo() {}

    Foo(std::initializer_list<Foo>) {
        std::cout << "initializer list" << std::endl;
    }

    Foo(const Foo&) {
        std::cout << "copy ctor" << std::endl;
    }
};

int main() {
    Foo a;
    Foo b(a); // copy ctor
    Foo c{a}; // copy ctor (init. list element) + initializer list!!!
}

ধরে নিই যে আপনি এই জাতীয় ক্লাসের মুখোমুখি হচ্ছেন না অন্তর্নিদীকরণ তালিকাটি ব্যবহার না করার সামান্য কারণ আছে।


20
এটি জেনেরিক প্রোগ্রামিংয়ের একটি খুব গুরুত্বপূর্ণ বিষয়। আপনি যখন টেমপ্লেট লেখেন, আপনি শব্দার্থবিজ্ঞান (ভাল, এবং সম্ভবত কোনও অবজেক্ট কোনও অবজেক্ট তৈরির জন্য ) না চাইলে ব্র্যাসেড-আরিন-তালিকা (এর জন্য স্ট্যান্ডার্ডের নাম { ... }) ব্যবহার করবেন নাinitializer_list
জিও

82
std::initializer_listনিয়মটি কেন বিদ্যমান তা আমি সত্যই বুঝতে পারি না - এটি কেবল ভাষায় বিভ্রান্তি ও গোলযোগ যুক্ত করে। আপনি Foo{{a}}যদি std::initializer_listকনস্ট্রাক্টর চান তবে কি করতে ভুল হচ্ছে ? এটি std::initializer_listঅন্যান্য সমস্ত ওভারলোডের চেয়ে বেশি অগ্রাধিকার পাওয়ার চেয়ে বোঝা অনেক সহজ ।
ব্যবহারকারী 1520427

5
উপরের মন্তব্যের জন্য +1, কারণ এটি আমার মনে হয় সত্যিই জগাখিচুড়ি !! এটি যুক্তিযুক্ত নয়; Foo{{a}}আমার জন্য আরও কিছু যুক্তি অনুসরণ করে Foo{a}যা আন্তঃকরণকারী তালিকার অগ্রাধিকারে পরিণত হয় (ব্যবহারকারীরা এইচএম ভাবতে পারে ...)
গ্যাব্রিয়েল

32
মূলত সি ++ 11 একটি জগাখিরির সাথে অন্য জগাখিরি প্রতিস্থাপন করে। ওহ, দুঃখিত এটি এটি প্রতিস্থাপন করে না - এটি এতে যুক্ত করে। আপনি যদি এই ধরনের ক্লাসের মুখোমুখি না হন তবে আপনি কীভাবে জানতে পারবেন? আপনি যদি কনস্ট্রাক্টর ছাড়াই শুরু করেন std::initializer_list<Foo>তবে এর ইন্টারফেসটি প্রসারিত করার জন্য এটি কোনও সময়ে ক্লাসে যুক্ত হতে চলেছে Foo? তারপরে Fooক্লাসের ব্যবহারকারীরা বিভ্রান্ত হয়।
ডক

10
.. "ব্রেস ইনিশিয়ালাইজেশন ব্যবহারের অনেক কারণ" কী কী? এই উত্তরটি একটি কারণ ( initializer_list<>) নির্দেশ করে, যা এটি পছন্দ করে কে বলে এটি সত্যিই যোগ্যতা অর্জন করে না এবং তারপরে এটির পছন্দনীয় নয় এমন একটি ভাল ক্ষেত্রে উল্লেখ করার জন্য এগিয়ে যায় । আমি কী অনুভব করছি যে ~ 30 অন্যান্য লোক (2016-04-21 পর্যন্ত) সহায়ক বলে মনে করেছিল?
ডোয়ান্ডারসন

0

এটি কেবল ততক্ষণ নিরাপদ হবে যতক্ষণ না আপনি কোনও-সংকীর্ণের সাথে তৈরি করেন না যেমন গুগল ক্রোমিয়ামে বলে। যদি আপনি এটি করেন তবে তা নিরাপদ। এই পতাকা ব্যতীত কেবলমাত্র অনিরাপদ মামলাগুলি সি ++ ২০ দ্বারা স্থির করা হবে।

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

এই দুটি সমন্বিত অর্থ এর ভিতরে থাকা আদি স্থিরতা থাকলে তারা নিরাপদ তবে তারা বস্তু থাকলে কম নিরাপদ (যদিও এটি সি ++ তে স্থির করা হয়েছে)


আমি সোনারবোল্ট.আরোগ.আরজে নূডলিংয়ের চেষ্টা করেছিলাম "স্পষ্টত" বা "বেসরকারী" কনস্ট্রাক্টরদের স্যাম্পল কোড ব্যবহার করে এবং একটি বা অন্যটিকে ব্যক্তিগত বা স্পষ্ট করে বাইপাস করতে এবং উপযুক্ত সংকলক ত্রুটির সাথে পুরস্কৃত হয়েছিল [গুলি]। কিছু নমুনা কোড সহ এটি ব্যাক আপ যত্ন?
মার্ক স্টোর 17

এটি সি ++ 20 এর জন্য প্রস্তাবিত সমস্যার সমাধান: ওপেন-std.org/jtc1/sc22/wg21/docs/papers/2018/p1008r1.pdf
অ্যালান জেনসেন

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