স্ট্যান্ড :: মেক_ পেয়ার বনাম স্ট্যান্ড :: জোড় এর কনস্ট্রাক্টরের উদ্দেশ্য কী?


180

এর উদ্দেশ্য কী std::make_pair?

কেন শুধু না std::pair<int, char>(0, 'a')?

দুটি পদ্ধতির মধ্যে কি কোনও পার্থক্য রয়েছে?


6
সি ++ 11 এ আপনি মেক_ পেয়ার ছাড়াই প্রায় সম্পূর্ণ করতে পারেন। আমার উত্তর দেখুন ।
প্লেগহ্যামার

2
সি ++ 17 এ, std::make_pairঅতিরিক্ত কাজ। এর নীচে একটি উত্তর রয়েছে যা এটি বিশদ করে।
ড্রু ডোরম্যান

উত্তর:


165

পার্থক্যটি হ'ল std::pairআপনার সাথে উভয় উপাদানের প্রকারগুলি নির্দিষ্ট করা দরকার, যেখানে std::make_pairআপনাকে এটি বলার প্রয়োজন ছাড়াই এটিকে যে উপাদানগুলিতে প্রেরণ করা হয় তার প্রকারের সাথে একটি জুড়ি তৈরি করবে। এটাই আমি বিভিন্ন ডক্স থেকে যাইহোক সংগ্রহ করতে পারি।

Http://www.cplusplus.com/references/std/utility/make_pair/ থেকে এই উদাহরণটি দেখুন

pair <int,int> one;
pair <int,int> two;

one = make_pair (10,20);
two = make_pair (10.5,'A'); // ok: implicit conversion from pair<double,char>

এর অন্তর্নিহিত রূপান্তর বোনাস বাদে আপনি যদি Make_pair ব্যবহার না করেন তবে আপনাকে করতে হবে

one = pair<int,int>(10,20)

প্রতিবার যখন আপনি একটিকে বরাদ্দ করেছেন যা সময়ের সাথে সাথে বিরক্তিকর হবে ...


1
প্রকৃতপক্ষে, প্রকারগুলি নির্দিষ্ট করার প্রয়োজন ছাড়াই সংকলন সময়ে ছাড় করা উচিত।
চাদ

@ টর হ্যাঁ, আমি জানি যে কীভাবে এই দুটোকেই ব্যবহার করতে হয়, এর কারণ থাকলে আমি কেবল কৌতূহলী ছিলাম std::make_pair। দৃশ্যত এটি কেবল সুবিধার জন্য।

@ জয় এটি প্রদর্শিত হবে।
টোর ভ্যালামো

15
আমি মনে করি আপনি one = {10, 20}আজকাল করতে পারেন তবে এটি পরীক্ষা করার জন্য আমার কাছে কোনও সি ++ 11 সংকলক নেই।
এমসাল্টার

6
এছাড়াও লক্ষ করুন যে make_pairস্ট্রোকস, ইউনিয়ন, ল্যাম্বডাস এবং অন্যান্য ডুডড সহ অজ্ঞাতনামা ধরণের সাথে কাজ করে।
ছানা

35

@ এসএমএলটাররা উপরের জবাব হিসাবে, আপনি এখন C ++ 11 এ করার জন্য কোঁকড়া ধনুর্বন্ধনী ব্যবহার করতে পারেন (এটি কেবলমাত্র C ++ 11 সংকলক দিয়ে যাচাই করেছেন):

pair<int, int> p = {1, 2};

27

শ্রেণি টেম্পলেট আর্গুমেন্ট সি ++ 17 এর আগে কনস্ট্রাক্টর থেকে অনুমান করা যায়নি

সি ++ 17 এর আগে আপনি এমন কিছু লিখতে পারেন নি:

std::pair p(1, 'a');

যেহেতু এটি নির্মাণকারী যুক্তি থেকে টেমপ্লেট প্রকারগুলি নির্ধারণ করবে।

সি ++ 17 সেই বাক্য গঠনটিকে সম্ভব করে তোলে এবং তাই make_pairঅপ্রয়োজনীয়।

সি ++ 17 এর আগে, std::make_pairআমাদের কম ভার্বোজ কোড লেখার অনুমতি দিল:

MyLongClassName1 o1;
MyLongClassName2 o2;
auto p = std::make_pair(o1, o2);

আরও ভার্বোজের পরিবর্তে:

std::pair<MyLongClassName1,MyLongClassName2> p{o1, o2};

যা ধরণের পুনরাবৃত্তি করে এবং খুব দীর্ঘ হতে পারে।

প্রকারের অনুমানটি সেই প্রাক-সি ++ 17 ক্ষেত্রে কাজ করে কারণ make_pairকোনও নির্মাণকারী নয়।

make_pair মূলত এর সমতুল্য:

template<class T1, class T2>
std::pair<T1, T2> my_make_pair(T1 t1, T2 t2) {
    return std::pair<T1, T2>(t1, t2);
}

একই ধারণা প্রযোজ্য inserterবনাম insert_iterator

আরো দেখুন:

নূন্যতম উদাহরণ

জিনিসগুলিকে আরও কংক্রিট করার জন্য, আমরা সমস্যাটি ন্যূনতমভাবে পর্যবেক্ষণ করতে পারি:

main.cpp

template <class MyType>
struct MyClass {
    MyType i;
    MyClass(MyType i) : i(i) {}
};

template<class MyType>
MyClass<MyType> make_my_class(MyType i) {
    return MyClass<MyType>(i);
}

int main() {
    MyClass<int> my_class(1);
}

তারপর:

g++-8 -Wall -Wextra -Wpedantic -std=c++17 main.cpp

সুখে কম্পাইল করে তবে:

g++-8 -Wall -Wextra -Wpedantic -std=c++14 main.cpp

এর সাথে ব্যর্থ:

main.cpp: In function int main()’:
main.cpp:13:13: error: missing template arguments before my_class
     MyClass my_class(1);
             ^~~~~~~~

এবং পরিবর্তে কাজ করা প্রয়োজন:

MyClass<int> my_class(1);

বা সহায়ক:

auto my_class = make_my_class(1);

যা কনস্ট্রাক্টরের পরিবর্তে নিয়মিত ফাংশন ব্যবহার করে।

স্ট্যান্ডার্ড :: রেফারেন্স_ওয়ার্পারের জন্য পার্থক্য

এই মন্তব্যে উল্লেখ করা হয়েছে যে std::make_pairআন্র্যাপিংগুলি std::reference_wrapperযখন কনস্ট্রাক্টর না করে, সুতরাং এটির একটি পার্থক্য। TODO উদাহরণ।

জিসিসি 8.1.0, উবুন্টু 16.04 দিয়ে পরীক্ষিত ।


1
"সি ++ 17 সেই বাক্য গঠনটিকে সম্ভব করে তোলে এবং সেইজন্য Make_pair অপ্রয়োজনীয়।" - কেন এটি std::make_pairসি ++ 17 এ অবহেলিত হয়নি?
অ্যান্ড্রি

@ এবং ড্রি আমি নিশ্চিত নই, সম্ভাব্য কারণ হ'ল এটি কোনও সমস্যা সৃষ্টি করে না তাই পুরানো কোডটি ভাঙার দরকার নেই? তবে আমি সি ++ কমিটির যুক্তির সাথে পরিচিত নই, আপনি যদি কিছু খুঁজে পান তবে আমাকে পিং করুন।
সিরো সান্তিলি 郝海东 冠状 病 六四 事件 法轮功

1
একটি দরকারী জিনিস যা আমি এসেছি তা হ'ল std :: Make_pair <T1, T2> (o1, o2) দিয়ে প্রকারগুলি নির্দিষ্ট করতে সক্ষম হওয়া ব্যবহারকারীকে o1 বা o2 প্রকারের ভুল করতে বাধা দেয় যা স্পষ্টতই হতে পারে না টি 1 বা টি 2 তে কাস্ট করুন। উদাহরণস্বরূপ একটি স্বাক্ষরবিহীন প্রান্তে নেতিবাচক সংখ্যাটি পাস করা। -সাইন-রূপান্তর-ওয়ারার্ড এই ত্রুটিটি ধরবে না std :: c ++ 11 এর মধ্যে জোড় নির্মাণকারী তবে std :: Make_pair ব্যবহার করা থাকলে এটি ত্রুটিটি ধরবে।
কনচিচিয়া

make_pairরেফারেন্সের মোড়কগুলি মোড়কজাত করে, তাই এটি আসলে সিটিএডি থেকে আলাদা।
এলএফ

26

নির্দিষ্ট ধরণের আর্গুমেন্টের সাথে কনস্ট্রাক্টরকে make_pairস্পষ্টভাবে কল করা এবং কল করার মধ্যে কোনও পার্থক্য নেই pairstd::make_pairপ্রকারগুলি ভার্বোজ করার সময় আরও সুবিধাজনক কারণ কোনও টেম্পলেট পদ্ধতিতে প্রদত্ত প্যারামিটারের ভিত্তিতে টাইপ ছাড় থাকে has উদাহরণ স্বরূপ,

std::vector< std::pair< std::vector<int>, std::vector<int> > > vecOfPair;
std::vector<int> emptyV;

// shorter
vecOfPair.push_back(std::make_pair(emptyV, emptyV));

 // longer
vecOfPair.push_back(std::pair< std::vector<int>, std::vector<int> >(emptyV, emptyV));

21

এটি লক্ষণীয় যে এটি সি ++ টেম্পলেট প্রোগ্রামিংয়ের একটি সাধারণ প্রতিমা। এটা তোলে অবজেক্ট জেনারেটর বাগ্ধারা, একে বলা হয়, আপনি আরও তথ্য এবং একটি সুন্দর উদাহরণ জানতে পারেন এখানে

সম্পাদনা হিসাবে কেউ মন্তব্যে পরামর্শ দেওয়ার পরে (অপসারণ থেকে) নিম্নলিখিতটি লিঙ্কটি ভেঙে যাওয়ার ক্ষেত্রে সামান্য পরিবর্তিত এক্সট্রাক্ট।

একটি অবজেক্ট জেনারেটর স্পষ্টভাবে তাদের ধরণগুলি নির্দিষ্ট না করেই বস্তু তৈরির অনুমতি দেয়। এটি ফাংশন টেম্পলেটগুলির একটি দরকারী সম্পত্তির উপর ভিত্তি করে যা শ্রেণীর টেমপ্লেটগুলি নেই: ফাংশন টেমপ্লেটের ধরণের পরামিতিগুলি তার আসল পরামিতিগুলি থেকে স্বয়ংক্রিয়ভাবে কেটে নেওয়া হয় u std::make_pairএকটি সাধারণ উদাহরণ যা ফাংশনের std::pairআসল পরামিতিগুলির উপর নির্ভর করে টেম্পলেটটির একটি উদাহরণ std::make_pairদেয়।

template <class T, class U>
std::pair <T, U> 
make_pair(T t, U u)
{
  return std::pair <T, U> (t,u);
}

2
@duck আসলে &&সি ++ 11 সাল থেকে।
Justme0

5

Make_pair সরাসরি নির্মাণকারীর উপর একটি অতিরিক্ত অনুলিপি তৈরি করে। আমি সর্বদা সহজ সিনট্যাক্স সরবরাহ করতে আমার জোড়া টাইপ করি।
এটি তফাতটি দেখায় (উদাহরণস্বরূপ রামপাল চৌধুরী):

class Sample
{
    static int _noOfObjects;

    int _objectNo;
public:
    Sample() :
        _objectNo( _noOfObjects++ )
    {
        std::cout<<"Inside default constructor of object "<<_objectNo<<std::endl;
    }

    Sample( const Sample& sample) :
    _objectNo( _noOfObjects++ )
    {
        std::cout<<"Inside copy constructor of object "<<_objectNo<<std::endl;
    }

    ~Sample()
    {
        std::cout<<"Destroying object "<<_objectNo<<std::endl;
    }
};
int Sample::_noOfObjects = 0;


int main(int argc, char* argv[])
{
    Sample sample;
    std::map<int,Sample> map;

    map.insert( std::make_pair( 1, sample) );
    //map.insert( std::pair<int,Sample>( 1, sample) );
    return 0;
}

4
আমি পুরোপুরি নিশ্চিত যে অতিরিক্ত সংকলনটি সব ক্ষেত্রেই আলাদা করা হবে, যদি সংকলকের অপ্টিমাইজেশন সেটিংস পর্যাপ্ত পরিমাণে থাকে।
বিজার্ন পোল্লেক্স

1
আপনি কেন কখনও সংশোধন করার জন্য সংকলক অপ্টিমাইজেশনের উপর নির্ভর করতে চান?
sjbx

আমি উভয় সংস্করণে এবং std::moveকেবল অভ্যন্তরে insertএবং / বা এর কোন রেফারেন্স হবে তার চারপাশে একই ফলাফল পেয়েছি sample। এটা কেবলমাত্র যখন আমি পরিবর্তন std::map<int,Sample>করতে std::map<int,Sample const&>যে আমি নির্মাণ বস্তু সংখ্যা কমাতে, এবং শুধুমাত্র যখন আমি কপি কন্সট্রাকটর যে আমি সব কপি (স্পষ্টত) নিষ্কাশন মুছে দিন। এই দুটি পরিবর্তন করার পরে, আমার ফলাফলের মধ্যে ডিফল্ট কনস্ট্রাক্টরের একটি কল এবং একই বস্তুর জন্য ডেস্ট্রাক্টরের কাছে দুটি কল অন্তর্ভুক্ত থাকে। আমার মনে হয় আমি অবশ্যই কিছু মিস করছি। (g ++ 5.4.1, c ++ 11)
জন পি

FWIW আমি সম্মত হই যে অপটিমাইজেশন এবং নির্ভুলতা সম্পূর্ণ স্বাধীন হওয়া উচিত, কারণ বিভিন্ন অপ্টিমাইজেশনের স্তরগুলি অসামঞ্জস্যিত ফলাফলের পরে ঠিক এই ধরণের কোড হিসাবে আপনি স্যানিটি চেক হিসাবে লেখেন। সাধারণভাবে আমি এর emplaceপরিবর্তে সুপারিশ করব insertযদি আপনি কেবল তাত্ক্ষণিকভাবে sertোকানোর জন্য কোনও মান তৈরি করে থাকেন (এবং আপনি অতিরিক্ত উদাহরণ চান না)) এটি আমার দক্ষতার ক্ষেত্র নয়, যদি আমি এমনকি বলতে পারি যে আমার একটি আছে তবে অনুলিপি / সরানো সি ++ 11 দ্বারা প্রবর্তিত শব্দার্থবিজ্ঞানগুলি আমাকে অনেক সাহায্য করেছে।
জন পি

আমি বিশ্বাস করি যে আমি ঠিক একই সমস্যাটির মুখোমুখি হয়েছি এবং পুরো সন্ধ্যা সম্পর্কে ডিবাগিংয়ের পরে, অবশেষে আমি এখানে এসেছি।
lllllllllllll

1

সি ++ 11 থেকে শুরু করে জোড়ার জন্য অভিন্ন সূচনা ব্যবহার করুন। এর পরিবর্তে:

std::make_pair(1, 2);

অথবা

std::pair<int, int>(1, 2);

শুধু ব্যবহার

{1, 2};

{1, 2}একটি জোড়া শুরু করতে ব্যবহার করা যেতে পারে, তবে টাইপ জোড়ের জন্য প্রতিশ্রুতিবদ্ধ না। অর্থাত যখন স্বয়ং ব্যবহার করে আপনি RHS উপর একটি টাইপ কমিট করতে হবে: auto p = std::pair{"Tokyo"s, 9.00};
মার্কাস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.