অনুলিপি আর সরাসরি সূচনা করার মধ্যে কি পার্থক্য রয়েছে?


244

ধরুন আমার এই ফাংশনটি রয়েছে:

void my_test()
{
    A a1 = A_factory_func();
    A a2(A_factory_func());

    double b1 = 0.5;
    double b2(0.5);

    A c1;
    A c2 = A();
    A c3(A());
}

প্রতিটি গ্রুপে এই বিবৃতিগুলি কি অভিন্ন? বা কিছু প্রাথমিককরণে অতিরিক্ত (সম্ভবত অপ্টিমাইজযোগ্য) কপি রয়েছে?

আমি মানুষ দুটি জিনিস বলতে দেখেছি। দয়া করে cite প্রমাণ হিসাবে পাঠ্য। দয়া করে অন্যান্য কেস যুক্ত করুন।


1
এবং সেখানে চতুর্থ মামলাটি আলোচনা করেছেন @ জোহনেস শ্যাব - A c1; A c2 = c1; A c3(c1);
ড্যান নিসেনবাউম

1
মাত্র একটি 2018 নোট: নিয়মগুলি সি ++ 17 এ পরিবর্তিত হয়েছে , দেখুন, যেমন এখানে । যদি আমার বোধগম্যতা সঠিক হয়, সি ++ 17 এ, উভয় বক্তব্য কার্যকরভাবে এক রকম (এমনকি অনুলিপি কর্টর স্পষ্ট থাকলেও)। তদ্ব্যতীত, আরআর এক্সপ্রেশন যদি অন্য ধরণের হয়ে থাকে তবে Aঅনুলিপি করার জন্য অনুলিপি / মুভ কনডাক্টরের অস্তিত্বের প্রয়োজন হবে না। এই কারণেই std::atomic<int> a = 1;সি ++ 17 এ ঠিক আছে তবে আগে নয়।
ড্যানিয়েল ল্যাঙ্গার

উত্তর:


246

সি ++ 17 আপডেট

সি ++ ১ In-এ, এই অধ্যায়টি সি ++ 17-এ A_factory_func()(আলগাভাবে কথা বলার জন্য) যে কোনও বস্তুর আরম্ভ করা হয়েছে কেবলমাত্র একটি অস্থায়ী বস্তু (সি ++ <= 14) তৈরি করা থেকে পরিবর্তনের অর্থ পরিবর্তিত হয়েছে। এই বস্তুগুলি ("রেজাল্ট অবজেক্টস" নামে পরিচিত) a1হ'ল ঘোষণাপত্র (যেমন ) দ্বারা তৈরি করা ভেরিয়েবল , যখন আরম্ভটি শেষ করে ফেলে দেওয়া হয় তখন তৈরি করা কৃত্রিম বস্তু বা রেফারেন্স বাইন্ডিংয়ের জন্য যদি কোনও বস্তুর প্রয়োজন হয় (যেমন, ইন A_factory_func();। শেষ ক্ষেত্রে, কোনও বস্তু কৃত্রিমভাবে তৈরি করা হয়, তাকে "অস্থায়ী ধাতবকরণ" বলা হয়, কারণ A_factory_func()কোনও ভেরিয়েবল বা রেফারেন্স নেই যা অন্যথায় কোনও বস্তুর অস্তিত্বের প্রয়োজন হবে)।

উদাহরণস্বরূপ , আমাদের ক্ষেত্রে উদাহরণ হিসাবে a1এবং a2বিশেষ বিধিগুলি বলে যে এই জাতীয় ঘোষণায়, একই ধরণের একটি প্রলু ইনিশিয়ালাইজারের ফলাফল অবজেক্টটি a1পরিবর্তনশীল a1, এবং সেইজন্য A_factory_func()সরাসরি বস্তুটি আরম্ভ করে a1। কোনও মধ্যস্থতাকারী কার্যকরী-শৈলীর cast A_factory_func(another-prvalue)ালির কোনও প্রভাব পড়বে না, কারণ কেবলমাত্র বাইরের মূল্যগুলির ফলাফল অবজেক্টটি "অভ্যন্তরীণ মূল্যবৃত্তের ফলাফল অবজেক্ট" হতে পারে।


A a1 = A_factory_func();
A a2(A_factory_func());

কি ধরণের A_factory_func()রিটার্ন নির্ভর করে । আমি ধরে নিলাম এটি কোনও ফেরত দেয় A- তবে এটি একই করছে - ব্যতীত যখন অনুলিপিটি নির্মাণকারী স্পষ্ট হয়, তবে প্রথমটি ব্যর্থ হবে। 8.6 / 14 পড়ুন

double b1 = 0.5;
double b2(0.5);

এটি একই কাজ করছে কারণ এটি একটি বিল্ট-ইন টাইপ (এর অর্থ এখানে শ্রেণীবদ্ধ নয়)। 8.6 / 14 পড়ুন ।

A c1;
A c2 = A();
A c3(A());

এটি একই করছে না। প্রথম ডিফল্ট-আরম্ভকরণ যদি Aকোনও নন-পিওডি হয়, এবং কোনও পিওডের জন্য কোনও আরম্ভ করে না (পড়ুন 8.6 / 9 )। দ্বিতীয় অনুলিপিটি আরম্ভ করে: মানটি একটি অস্থায়ী হয় এবং তারপরে সেই মানটি অনুলিপি করে c2( 5.2.3 / 2 এবং 8.6 / 14 পড়ুন )। অবশ্যই এটির জন্য একটি স্পষ্ট অনুলিপি অনুলিপি প্রস্তুতকারকের (পড়ুন 8.6 / 14 এবং 12.3.1 / 3 এবং 13.3.1.3/1 পড়ুন )। তৃতীয়টি একটি ফাংশনটির জন্য একটি ফাংশন ঘোষণা তৈরি করে c3যা কোনওটি প্রদান করে Aএবং এটি কোনও ফাংশন পয়েন্টারটি কোনও ফাংশনে ফিরে আসে A(পড়ুন 8.2 )।


ইনিশিয়ালাইজেশন সরাসরি এবং অনুলিপি সূচনাতে ডেলিভেশন

তারা অভিন্ন দেখতে দেখতে এবং একই কাজ করার কথা থাকলেও এই দুটি ফর্ম নির্দিষ্ট ক্ষেত্রে উল্লেখযোগ্যভাবে আলাদা। আরম্ভের দুটি রূপ হ'ল প্রত্যক্ষ এবং অনুলিপি সূচনা:

T t(x);
T t = x;

এমন একটি আচরণ রয়েছে যা আমরা তাদের প্রত্যেকটির প্রতি বিশেষণ দিতে পারি:

  • ডাইরেক্ট ইনিশিয়ালাইজেশন হ'ল ওভারলোডেড ফাংশনটিতে একটি ফাংশন কলের মতো আচরণ করে: ফাংশনগুলি এই ক্ষেত্রে, T(যার সাথে explicitরয়েছে) এর নির্মাণকারী এবং যুক্তিটি হ'ল x। ওভারলোড রেজোলিউশনটি সেরা ম্যাচিং কনস্ট্রাক্টরকে সন্ধান করবে এবং যখন প্রয়োজন হবে তখন কোনও সংক্রামিত রূপান্তর প্রয়োজন।
  • অনুলিপিকরণ সূচনাটি একটি অন্তর্নিহিত রূপান্তর ক্রম তৈরি করে: এটি xকোনও ধরণের অবজেক্টে রূপান্তরিত করার চেষ্টা করে T। (এটি তখন সেই বস্তুটির উপর থেকে আরম্ভ করা অবজেক্টে অনুলিপি করতে পারে, সুতরাং একটি অনুলিপি নির্মাণকারীও প্রয়োজন - তবে এটি নীচে গুরুত্বপূর্ণ নয়)

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

আমি চেষ্টা করেছি এবং কনস্ট্রাক্টরের মাধ্যমে "সুস্পষ্ট" ব্যবহার না করে without ফর্মগুলির প্রত্যেকের জন্য আলাদা আলাদা পাঠ্য আউটপুট দেওয়ার জন্য নিম্নলিখিত কোডটি পেয়েছিexplicit

#include <iostream>
struct B;
struct A { 
  operator B();
};

struct B { 
  B() { }
  B(A const&) { std::cout << "<direct> "; }
};

A::operator B() { std::cout << "<copy> "; return B(); }

int main() { 
  A a;
  B b1(a);  // 1)
  B b2 = a; // 2)
}
// output: <direct> <copy>

এটি কীভাবে কাজ করে এবং এর ফলাফল কী করে?

  1. সরাসরি সূচনা

    এটি প্রথমে রূপান্তর সম্পর্কে কিছুই জানে না। এটি কেবল কোনও নির্মাণকারীকে কল করার চেষ্টা করবে। এই ক্ষেত্রে, নিম্নলিখিত নির্মাণকারী উপলব্ধ এবং একটি সঠিক মিল :

    B(A const&)

    কোনও রূপান্তর নেই, একজন ব্যবহারকারী সংজ্ঞায়িত রূপান্তরটির চেয়ে কম, সেই কনস্ট্রাক্টরকে কল করার প্রয়োজন (নোট করুন যে কোনও কনস্টের যোগ্যতার রূপান্তরটি এখানে হয় না)। এবং তাই সরাসরি সূচনা এটি কল করবে।

  2. অনুলিপি অনুলিপি করুন

    যেমনটি উপরে বলা হয়েছে, অনুলিপি করা যখন রূপান্তর ক্রম তৈরি করবে যা এগুলি থেকে aটাইপ Bবা প্রাপ্ত হয়নি (যা এখানে স্পষ্টতই কেস হয়)। সুতরাং এটি রূপান্তর করার উপায় অনুসন্ধান করবে এবং নীচের প্রার্থীদের সন্ধান করবে

    B(A const&)
    operator B(A&);

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

    মনে রাখবেন যে আমরা যদি রূপান্তর ফাংশনটিকে কনস্টের সদস্য ফাংশন হিসাবে পরিবর্তন করি তবে রূপান্তরটি অস্পষ্ট (কারণ উভয়েরই প্যারামিটার ধরণের থাকে A const&): কম্যু সংকলক এটিকে সঠিকভাবে প্রত্যাখ্যান করে, তবে জিসিসি এটিকে নন-প্যাডেন্টিক মোডে গ্রহণ করে। স্যুইচিং -pedanticএটিকে সঠিক অস্পষ্টতার সতর্কতাটিকে আউটপুট করে তোলে though

আমি আশা করি এটি এই দুটি ফর্মের পার্থক্য কীভাবে তা পরিষ্কার করে তুলতে কিছুটা সহায়তা করবে!


কি দারুন. আমি এমনকি কার্য ঘোষণার সম্পর্কে বুঝতে পারি না। আমি আপনার উত্তরটি কেবলমাত্র একমাত্র সেই সম্পর্কে জানার জন্য গ্রহণ করতে হবে। কোনও কারণ আছে যে ফাংশন ঘোষণাগুলি সেভাবে কাজ করে? C3 এর সাথে কোনও ফাংশনের অভ্যন্তরে অন্যরকম আচরণ করা ভাল হবে।
rlbond

4
বাহ, দুঃখিত ভাবেন, তবে নতুন ফর্ম্যাটিং ইঞ্জিনের কারণে আমাকে আমার মন্তব্যটি সরিয়ে আবার পোস্ট করতে হয়েছিল: এটি কারণ ফাংশন পরামিতিগুলিতে R() == R(*)()এবং T[] == T*। এটি হ'ল ফাংশন প্রকারগুলি হ'ল ফাংশন পয়েন্টার প্রকার এবং অ্যারে প্রকারগুলি পয়েন্টার-থেকে-উপাদান ধরণের। এই স্তন্যপান। এটি প্রায়শই কাজ করা যায় A c3((A()));(অভিব্যক্তির চারপাশে প্যারেনস)।
জোহানেস স্কাউব -

4
আমি জিজ্ঞাসা করতে পারি "" পড়ুন 8.5 / 14 "এর অর্থ কী? কী বোঝায়? একটি বই? একটি অধ্যায়? একটি ওয়েবসাইট?
এজেপি

9
@ এসএপি-তে অনেক লোকেরা প্রায়শই সি ++ অনুষদের রেফারেন্স চান এবং আরএলবন্ডের অনুরোধ "অনুগ্রহ করে পাঠ্যকে প্রমাণ হিসাবে উল্লেখ করুন" এর প্রতিক্রিয়ায় আমি এখানে যা করেছি তা হ'ল। আমি অনুমিতিটি উদ্ধৃত করতে চাই না, যেহেতু এটি আমার উত্তরকে স্নাতক করে দেয় এবং আপ টু ডেট রাখার জন্য আরও অনেক বেশি কাজ (অপ্রয়োজনীয়)।
জোহানেস স্কাউব -

1
@ লুকা আমি এর জন্য একটি নতুন প্রশ্ন শুরু করার পুনরুদ্ধার করছি যাতে লোকেরা
যেভাবে

49

অ্যাসাইনমেন্টটি আরম্ভের থেকে পৃথক ।

নিম্নলিখিত দুটি লাইনই প্রাথমিককরণ করে । একটি একক নির্মাণকারী কল করা হয়েছে:

A a1 = A_factory_func();  // calls copy constructor
A a1(A_factory_func());   // calls copy constructor

তবে এটি এর সমতুল্য নয়:

A a1;                     // calls default constructor
a1 = A_factory_func();    // (assignment) calls operator =

এটি প্রমাণ করার জন্য আমার কাছে এই মুহুর্তে কোনও পাঠ্য নেই তবে এটি পরীক্ষা করা খুব সহজ:

#include <iostream>
using namespace std;

class A {
public:
    A() { 
        cout << "default constructor" << endl;
    }

    A(const A& x) { 
        cout << "copy constructor" << endl;
    }

    const A& operator = (const A& x) {
        cout << "operator =" << endl;
        return *this;
    }
};

int main() {
    A a;       // default constructor
    A b(a);    // copy constructor
    A c = a;   // copy constructor
    c = b;     // operator =
    return 0;
}

2
ভাল রেফারেন্স: "সি সি ++ প্রোগ্রামিং ল্যাঙ্গুয়েজ, বিশেষ সংস্করণ" বার্জন স্ট্রস্ট্রপ দ্বারা, বিভাগ 10.4.4.1 (পৃষ্ঠা 245)। অনুলিপি এবং অনুলিপি নিয়োগের বিবরণ এবং কেন তারা মৌলিকভাবে পৃথক (যদিও তারা উভয়ই সিনট্যাক্স হিসাবে = অপারেটর ব্যবহার করে) বর্ণনা করে।
নাফ

গৌণ নিট, তবে আমি সত্যিই পছন্দ করি না যখন লোকেরা বলে যে "এ এ (এক্স)" এবং "এ এ = এক্স" সমান। কঠোরভাবে তারা না। প্রচুর ক্ষেত্রে তারা ঠিক একই কাজ করবে তবে যুক্তি তৈরির ভিত্তিতে বিভিন্ন নির্মাণকারীকে প্রকৃতপক্ষে ডেকে আনা সম্ভব।
রিচার্ড কর্ডেন

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

@ মেহরদাদআফশারি জোহানিসের উত্তরের কোডে আপনি দুজনের মধ্যে কোনটি ব্যবহার করেন তার ভিত্তিতে আপনি আলাদা আউটপুট পাবেন get
ব্রায়ান গর্ডন

1
@ ব্রায়ান গর্ডন হ্যাঁ, আপনি ঠিক বলেছেন। তারা সমতুল্য নয়। আমি আমার সম্পাদনায় রিচার্ডের মন্তব্যে অনেক আগে সম্বোধন করেছি।
মেহরদাদ আফশারি

22

double b1 = 0.5; কনস্ট্রাক্টরের অন্তর্নিহিত কল।

double b2(0.5); সুস্পষ্ট কল।

পার্থক্যটি দেখতে নিম্নলিখিত কোডটি দেখুন:

#include <iostream>
class sss { 
public: 
  explicit sss( int ) 
  { 
    std::cout << "int" << std::endl;
  };
  sss( double ) 
  {
    std::cout << "double" << std::endl;
  };
};

int main() 
{ 
  sss ddd( 7 ); // calls int constructor 
  sss xxx = 7;  // calls double constructor 
  return 0;
}

যদি আপনার শ্রেণীর সুস্পষ্ট এবং অন্তর্নিহিত কলগুলির চেয়ে সুস্পষ্ট কোন কনডাক্টর না থাকে তবে অভিন্ন।


5
+1 টি। চমৎকার উত্তর. সুস্পষ্ট সংস্করণটিও নোট করা ভাল। যাইহোক, এটি লক্ষণীয় যে আপনার একসাথে একই কনস্ট্রাক্টর ওভারলোডের দুটি সংস্করণ থাকতে পারে না । সুতরাং, এটি কেবল সুস্পষ্ট ক্ষেত্রে সংকলন করতে ব্যর্থ হবে। যদি তারা উভয়ই সংকলন করে তবে তাদের একই রকম আচরণ করতে হবে।
মেহরদাদ আফশারি

4

প্রথম দলবদ্ধকরণ: এটি কী A_factory_funcদেয় তার উপর নির্ভর করে । প্রথম লাইনটি অনুলিপি করার অনুলিপিটির একটি উদাহরণ , দ্বিতীয় লাইনটি সরাসরি সূচনা । তাহলে A_factory_funcআয় একটি Aবস্তুর তারপর তারা হয় সমতুল্য, তারা উভয় কলের জন্য কপি কন্সট্রাকটর A, অন্যথায় প্রথম সংস্করণ প্রকারের একটি rvalue সৃষ্টি Aফেরত টাইপ জন্য একটি উপলব্ধ রূপান্তর অপারেটর থেকে A_factory_funcবা উপযুক্ত Aকনস্ট্রাকটর, এবং তারপর কনস্ট্রাক্ট অনুলিপি কন্সট্রাকটর আহ্বান a1এই থেকে অস্থায়ী। দ্বিতীয় সংস্করণটি উপযুক্ত নির্মাতাদের সন্ধানের চেষ্টা করে যা যা কিছু A_factory_funcদেয়, বা এটি এমন কিছু লাগে যা প্রত্যাবর্তনের মানকে স্পষ্টত রূপান্তরিত করতে পারে।

দ্বিতীয় দলবদ্ধকরণ: হুবহু একই যুক্তি ধরে রাখে, প্রকারভেদে নির্মিত কোনও বিদেশী নির্মাণকারীর না থাকে তাই তারা বাস্তবে, অভিন্ন।

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


4

নোট:

[12.2 / 1] Temporaries of class type are created in various contexts: ... and in some initializations (8.5).

অর্থাৎ, অনুলিপি-অনুলিখনের জন্য।

[12.8 / 15] When certain criteria are met, an implementation is allowed to omit the copy construction of a class object ...

অন্য কথায়, একটি ভাল সংকলক না কপি-আরম্ভের যখন এটি এড়ানো যায় জন্য একটি অনুলিপি তৈরি; পরিবর্তে এটি কেবল কনস্ট্রাক্টরকে সরাসরি কল করবে - যেমন প্রত্যক্ষ-প্রাথমিককরণের মতো।

অন্য কথায়, কপি-ইনিশিয়ালাইজেশন বেশিরভাগ ক্ষেত্রে সরাসরি-ইনিশিয়ালাইজের মতোই হয় <সমীক্ষা> যেখানে বোধগম্য কোড লেখা হয়েছে। যেহেতু প্রত্যক্ষ-সূচনাটি সম্ভাব্যভাবে স্বেচ্ছাচারী (এবং তাই সম্ভবত অজানা) রূপান্তরগুলির কারণ হয়, তাই আমি যখন সম্ভব হয় তখন সর্বদা অনুলিপি-আরম্ভ ব্যবহার করতে পছন্দ করি। (বোনাসের সাথে এটি দেখতে আসলে আরম্ভের মতো লাগে like) </ p>

প্রযুক্তিগত গৌরব: [উপরে থেকে 12.2 / 1 সমাপ্তি] Even when the creation of the temporary object is avoided (12.8), all the semantic restrictions must be respected as if the temporary object was created.

খুশি আমি একটি সি ++ সংকলক লিখছি না।


4

আপনি কোনও বস্তুর সূচনা করার সময় আপনি এর নির্মাণক explicitএবং implicitপ্রকারের পার্থক্য দেখতে পাবেন :

শ্রেণি:

class A
{
    A(int) { }      // converting constructor
    A(int, int) { } // converting constructor (C++11)
};

class B
{
    explicit B(int) { }
    explicit B(int, int) { }
};

এবং main কার্য:

int main()
{
    A a1 = 1;      // OK: copy-initialization selects A::A(int)
    A a2(2);       // OK: direct-initialization selects A::A(int)
    A a3 {4, 5};   // OK: direct-list-initialization selects A::A(int, int)
    A a4 = {4, 5}; // OK: copy-list-initialization selects A::A(int, int)
    A a5 = (A)1;   // OK: explicit cast performs static_cast

//  B b1 = 1;      // error: copy-initialization does not consider B::B(int)
    B b2(2);       // OK: direct-initialization selects B::B(int)
    B b3 {4, 5};   // OK: direct-list-initialization selects B::B(int, int)
//  B b4 = {4, 5}; // error: copy-list-initialization does not consider B::B(int,int)
    B b5 = (B)1;   // OK: explicit cast performs static_cast
}

ডিফল্টরূপে, একজন কনস্ট্রাক্টর যেমন হয় implicitআপনি এটি আরম্ভ করার দুটি উপায় আছে:

A a1 = 1;        // this is copy initialization
A a2(2);         // this is direct initialization

এবং কোনও কাঠামোটিকে explicitকেবলমাত্র আপনার কাছে সরাসরি হিসাবে সরাসরিভাবে নির্ধারণ করে:

B b2(2);        // this is direct initialization
B b5 = (B)1;    // not problem if you either use of assign to initialize and cast it as static_cast

3

এই অংশটি সম্পর্কে শ্রদ্ধার সাথে জবাব দেওয়া:

এ সি 2 = এ (); এ সি 3 (এ ());

যেহেতু বেশিরভাগ উত্তর প্রাক-সি ++ 11 হওয়ায় আমি সি ++ 11 এ সম্পর্কে যা বলতে চাই তা যুক্ত করছি:

একটি প্রথম-টাইপ-স্পেসিফায়ার (7.1.6.2) বা টাইপনেম-স্পেসিফায়ার (14.6) এর পরে একটি প্রথম বন্ধনীযুক্ত এক্সপ্রেশন-তালিকাটি এক্সপ্রেশন তালিকা প্রদত্ত নির্দিষ্ট ধরণের মান নির্মান করে। যদি অভিব্যক্তি তালিকার একটি একক অভিব্যক্তি হয় তবে ধরণের রূপান্তর এক্সপ্রেশনটি সংশ্লিষ্ট কাস্ট এক্সপ্রেশন (5.4) এর সমতুল্য (সংজ্ঞায়িত, এবং যদি অর্থ সংজ্ঞায়িত হয়) হয়। নির্দিষ্ট করা ধরণটি একটি শ্রেণির ধরণ হলে শ্রেণীর ধরণটি সম্পূর্ণ হবে। যদি অভিব্যক্তি তালিকাটি একক মানের চেয়ে বেশি নির্দিষ্ট করে, প্রকারটি উপযুক্ত ঘোষিত নির্মাতা (8.5, 12.1) সহ একটি শ্রেণি হবে এবং টি (এক্স 1, এক্স 2, ...) টি টি-এর ঘোষণার সাথে সমান হবে (এক্স 1, এক্স 2, ...); কিছু উদ্ভাবিত অস্থায়ী পরিবর্তনশীল টির জন্য, ফলাফলটি মূল্যের হিসাবে টির মান হয়।

সুতরাং অপ্টিমাইজেশন না মান হিসাবে তারা সমতুল্য। নোট করুন যে এটি অন্যান্য উত্তরগুলির সাথে মিলেছে। যথার্থতার জন্য মানকটি কী বলে তা কেবল উদ্ধৃত করে।


আপনার উদাহরণগুলির "" এক্সপ্রেশন তালিকার কোনওটিই একক মানের চেয়ে বেশি নির্দিষ্ট করে না "। কীভাবে এটি সম্পর্কিত?
আন্ডারস্কোর_ডে

0

এই ক্ষেত্রে অনেকগুলি একটি অবজেক্টের বাস্তবায়নের সাপেক্ষে তাই আপনাকে একটি কঠিন উত্তর দেওয়া শক্ত।

কেস বিবেচনা করুন

A a = 5;
A a(5);

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

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

এটি বলেছিল, সংকলকটি কীভাবে কোডটিকে সর্বোত্তম করে তোলে তার নিজস্ব প্রভাব পড়বে have আমার কাছে যদি "=" অপারেটরকে কল করার আরম্ভকারী কনস্ট্রাক্টর থাকে - যদি সংকলকটি কোনও অপ্টিমাইজেশন না করে, উপরের লাইনটি নীচের লাইনের একটিটির বিপরীতে 2 টি জাম্প করবে।

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


এটি কোনও অপ্টিমাইজেশন নয় । কম্পাইলার আছে উভয় ক্ষেত্রেই সমভাবে কন্সট্রাকটর কল। ফলস্বরূপ, কেবলমাত্র operator =(const int)এবং না থাকলে তাদের কোনওটিই সংকলন করবে না A(const int)। আরও তথ্যের জন্য @ jia3ep এর উত্তর দেখুন।
মেহরদাদ আফশারি

আমি বিশ্বাস করি আপনি আসলে সঠিক তবে এটি একটি ডিফল্ট অনুলিপি নির্মাণকারী ব্যবহার করে ঠিক সূক্ষ্ম সংকলন করবে।
dborba

এছাড়াও, যেমনটি আমি উল্লেখ করেছি, একটি অনুলিপি নির্মাণকারীকে একটি অ্যাসাইনমেন্ট অপারেটর কল করা সাধারণ অনুশীলন, যেখানে সংকলক অপ্টিমাইজেশানগুলি কার্যকর হয়।
dborba

0

এটি সি -+ প্রোগ্রামিং ল্যাঙ্গুয়েজ থেকে লিখেছেন ব্জার্ন স্ট্রস্ট্রপ:

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

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