কেন আমি রেফারেন্সের ভেক্টর তৈরি করতে পারি না?


351

আমি যখন এটি করি:

std::vector<int> hello;

সবকিছু দুর্দান্ত কাজ করে। যাইহোক, আমি পরিবর্তে এটির রেফারেন্সের ভেক্টর তৈরি করলে:

std::vector<int &> hello;

আমি ভয়াবহ ত্রুটি মত পেতে

ত্রুটি C2528: 'পয়েন্টার': রেফারেন্সের নির্দেশকটি অবৈধ

আমি স্ট্রাক্টগুলিকে ভেক্টরে রেফারেন্সের একটি গুচ্ছ রাখতে চাই, যাতে আমাকে পয়েন্টারগুলির সাথে হস্তক্ষেপ করতে না হয়। কেন ভেক্টর এই সম্পর্কে কোনও তন্ত্র ছুঁড়ে ফেলছে? পরিবর্তে পয়েন্টারগুলির একটি ভেক্টর ব্যবহার করার জন্য কি আমার একমাত্র বিকল্প?


46
আপনি স্ট্যান্ড :: ভেক্টর <রেফারেন্স_ওয়ালা <int>> হ্যালো ব্যবহার করতে পারেন; দেখুন informit.com/guides/content.aspx?g=cplusplus&seqNum=217
অমিত

2
@ লিংকটি বৈধ নয়, সরকারী ডকুমেন্টেশন এখানে
মার্টিন

উত্তর:


339

ভেক্টরগুলির মতো ধারক ধরণের ধারক অবশ্যই নির্ধারিত হবে । রেফারেন্সগুলি বরাদ্দযোগ্য নয় (আপনি যখন তাদের ঘোষণা করা হয় কেবল তখনই আপনি সেগুলি শুরু করতে পারেন, এবং আপনি পরে সেগুলি অন্য কোনও উল্লেখ করতে পারবেন না)। অন্যান্য অ-নিয়োগযোগ্য প্রকারের ধারকগুলির উপাদান হিসাবেও অনুমোদিত নয়, যেমন vector<const int>অনুমোদিত নয়।


1
আপনি কি বলছেন আমার কাছে ভেক্টর নেই? (আমি নিশ্চিত যে আমি এটি করেছি ...)
জেমস কারান

8
হ্যাঁ, একটি স্টাডি :: ভেক্টর <স্টাডি :: ভেক্টর <int>> সঠিক, স্ট্যান্ড :: ভেক্টর নিয়োগযোগ্য।
মার্টিন কোট

17
প্রকৃতপক্ষে, এটি "আসল" কারণ। টি * টি টি এর পক্ষে টি এর পক্ষে অসম্ভব হওয়া সম্পর্কে ত্রুটিটি হ'ল লঙ্ঘিত প্রয়োজনীয়তার কেবলমাত্র একটি পার্শ্ব প্রতিক্রিয়া যা টি অবশ্যই অবশ্যই যোগ্য হতে হবে। যদি ভেক্টর টাইপ প্যারামিটারটি সঠিকভাবে পরীক্ষা করতে সক্ষম হয়, তবে এটি সম্ভবত "লঙ্ঘিত প্রয়োজনীয়তা: টি এবং
নিয়োগযোগ্য

2
অস্থায়ী ধারণাটি বুস্ট.আর.ডক / লিবস / ১/১৯৯/০//doc/html/Asignable.htmlস্বাপ বাদে সমস্ত ক্রিয়াকলাপ রেফারেন্সে বৈধ।
amit

7
এটি আর সত্য নয়। সি ++ ১১ যেহেতু, উপাদানটির একমাত্র অপারেশন-স্বতন্ত্র প্রয়োজন হ'ল "ক্ষয়যোগ্য", এবং উল্লেখটি নয়। স্ট্যাকওভারফ্লো / প্রশ্নগুলি / 33144419/ … দেখুন ।
laike9m

119

হ্যাঁ আপনি দেখতে পারেন, std::reference_wrapperএটি একটি রেফারেন্সের নকল করে তবে নির্ধারিত হয় এবং এটি "পুনর্নির্মাণ "ও করা যায়


4
get()এই মোড়কের কোনও ক্লাসের উদাহরণের কোনও পদ্ধতিতে অ্যাক্সেস করার চেষ্টা করার সময় কি প্রথমে কল করার কোনও উপায় আছে ? যেমন reference_wrapper<MyClass> my_ref(...); my_ref.get().doStuff();খুব রেফারেন্স হয় না।
টিমডিউলস

3
রেফারেন্সটি ফিরিয়ে দিয়ে তা কি টাইপটিতে ছদ্মবেশযুক্ত castালাইযোগ্য নয়?
ওয়ার্ল্ডসেন্ডার

3
হ্যাঁ, তবে এর জন্য একটি প্রসঙ্গ প্রয়োজন যা বোঝায় যে রূপান্তরটি প্রয়োজনীয়। সদস্য অ্যাক্সেস যে কাজ করে না, তাই প্রয়োজন .get()। কি timdiels চায় operator.; সে সম্পর্কে সর্বশেষ প্রস্তাব / আলোচনা একবার দেখুন।
আন্ডারস্কোর_

31

তাদের প্রকৃতির দ্বারা, রেফারেন্সগুলি কেবল তখনই তৈরি করা যেতে পারে যা সেগুলি তৈরি করা হয়; যেমন, নিম্নলিখিত দুটি লাইনের খুব আলাদা প্রভাব রয়েছে:

int & A = B;   // makes A an alias for B
A = C;         // assigns value of C to B.

আরও, এটি অবৈধ:

int & D;       // must be set to a int variable.

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


10
"আপনি যখন ভেক্টর তৈরি করেন, তৈরির সময় এটির আইটেমগুলিতে মান নির্ধারণের কোনও উপায় নেই" আপনি এই বিবৃতিতে কী বোঝাতে চাইছেন তা আমি বুঝতে পারি না। "এটি তৈরির আইটেমগুলি" কী কী? আমি একটি খালি ভেক্টর তৈরি করতে পারি। এবং আমি .push_back () দিয়ে আইটেমগুলি যুক্ত করতে পারি। আপনি কেবল উল্লেখ করছেন যে উল্লেখগুলি ডিফল্ট-গঠনমূলক নয়। তবে আমার কাছে অবশ্যই ক্লাসগুলির ভেক্টর থাকতে পারে যা ডিফল্ট-গঠনমূলক নয়।
newacct

2
এসডিডি :: ভেক্টর <টি> এর উপাদান ype ডিফল্ট গঠনমূলক হতে হবে না। আপনি স্ট্রাক্ট এ {এ (ইনট) লিখতে পারেন; ব্যক্তিগত: ক (); }; ভেক্টর <এ> এ; ঠিক আছে - যতক্ষণ না আপনি এমন পদ্ধতি ব্যবহার করেন না যেগুলির জন্য এটি ডিফল্ট গঠনের প্রয়োজন হয় (যেমন v.resize (100); - তবে পরিবর্তে আপনাকে v.resize (100, A (1)) করতে হবে;)
জোহানেস স্কাউব - লিটব

এবং এই ক্ষেত্রে আপনি কীভাবে এমন একটি পুশ_ব্যাক () লিখবেন? এটি এখনও অ্যাসাইনমেন্ট ব্যবহার করবে, নির্মাণ নয়।
জেমস কারান

3
জেমস কারান, সেখানে কোনও ডিফল্ট নির্মাণ হয় না। পূর্বনির্ধারিত বাফারে পুশ_ব্যাক প্লেসমেন্ট-নিউজ এ। এখানে দেখুন: স্ট্যাকওভারফ্লো . com / প্রশ্নগুলি / 672352/ … / মনে রাখবেন যে আমার দাবিটি কেবল ভেক্টর অ-ডিফল্ট-গঠনমূলক প্রকারগুলি পরিচালনা করতে পারে। আমি দাবি করি না, অবশ্যই এটি টি কে পরিচালনা করতে পারে (এটি অবশ্যই পারে না)।
জোহানেস স্কাউব - লিটব

29

অয়ন টোডেরেল ইতিমধ্যে হ্যাঁ ব্যবহার করে একটি উত্তর উল্লেখ করেছেন std::reference_wrapperসি ++ 11 যেহেতু আমাদের কাছে অবজেক্টটি পুনরুদ্ধার করতে std::vector এবং ব্যবহার করে রেফারেন্সটি সরিয়ে ফেলার একটি ব্যবস্থা আছে std::remove_reference। নীচে একটি উদাহরণ ব্যবহার কম্পাইল দেওয়া হয় g++এবং clangবিকল্প
-std=c++11এবং সফলভাবে মৃত্যুদন্ড কার্যকর।

#include <iostream>
#include <vector>
#include<functional>

class MyClass {
public:
    void func() {
        std::cout << "I am func \n";
    }

    MyClass(int y) : x(y) {}

    int getval()
    {
        return x;
    }

private: 
        int x;
};

int main() {
    std::vector<std::reference_wrapper<MyClass>> vec;

    MyClass obj1(2);
    MyClass obj2(3);

    MyClass& obj_ref1 = std::ref(obj1);
    MyClass& obj_ref2 = obj2;

    vec.push_back(obj_ref1);
    vec.push_back(obj_ref2);

    for (auto obj3 : vec)
    {
        std::remove_reference<MyClass&>::type(obj3).func();      
        std::cout << std::remove_reference<MyClass&>::type(obj3).getval() << "\n";
    }             
}

12
আমি std::remove_reference<>এখানে মান দেখতে পাচ্ছি না । বিন্দুটি std::remove_reference<>হ'ল আপনাকে "টাইপ টি লিখতে অনুমতি দেওয়া, তবে এটি যদি এক হয় তবে রেফারেন্স না পেয়ে"। তাই std::remove_reference<MyClass&>::typeলেখার মতোই MyClass
অ্যালিস্টায়ার

2
এতে মোটেই কোনও মূল্য নেই - আপনি কেবল লিখতে পারেন for (MyClass obj3 : vec) std::cout << obj3.getval() << "\n"; (বা for (const MyClass& obj3: vec)যদি আপনি getval()কনস্টকে ঘোষণা করেন , যেমনটি আপনার উচিত)।
টবি স্পিড

14

boost::ptr_vector<int> কাজ করবে.

সম্পাদনা: ব্যবহার করার পরামর্শ ছিল std::vector< boost::ref<int> >, যা কাজ করবে না কারণ আপনি ডিফল্ট-নির্মাণ করতে পারবেন না boost::ref


8
তবে আপনি কোনও ভেক্টর বা নন-ডিফল্ট-গঠনমূলক ধরনের থাকতে পারেন, তাই না? আপনাকে কেবলমাত্র ডিফল্ট কর্টরটি ব্যবহার না করার বিষয়ে সতর্ক থাকতে হবে। ভেক্টরের
ম্যানুয়েল

1
@ ম্যানুয়েল: বা resize
হালকাতা রেস

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

12

এটি সি ++ ভাষার একটি ত্রুটি। আপনি কোনও রেফারেন্সের ঠিকানা নিতে পারবেন না, যেহেতু এটি করার চেষ্টা করার ফলে অবজেক্টের ঠিকানা উল্লেখ করা হবে এবং সুতরাং আপনি কখনই কোনও রেফারেন্সের পয়েন্টার পেতে পারবেন না। std::vectorএর উপাদানগুলিতে পয়েন্টার সহ কাজ করে, সুতরাং সঞ্চিত মানগুলিকে নির্দেশ করতে সক্ষম হওয়া প্রয়োজন। পরিবর্তে আপনাকে পয়েন্টার ব্যবহার করতে হবে।


আমার ধারণা, এটি একটি শূন্য * বাফার এবং নতুন প্লেসমেন্ট ব্যবহার করে প্রয়োগ করা যেতে পারে। এটি এতটা অর্থবোধ করে না।
পিটারচেন

55
"ভাষায় ত্রুটি" খুব শক্তিশালী। এটি নকশা দ্বারা। আমি মনে করি না যে এটি প্রয়োজনীয় যে ভেক্টর উপাদানগুলির পয়েন্টারগুলির সাথে কাজ করে। তবে এটি প্রয়োজনীয় যে উপাদানটি যোগ্য হতে হবে। উল্লেখ নেই।
ব্রায়ান নিল

আপনি sizeofরেফারেন্সও নিতে পারবেন না ।
ডেভিড শোয়ার্টজ

1
আপনার কোনও রেফারেন্সের জন্য পয়েন্টার লাগবে না, আপনার রেফারেন্স রয়েছে, যদি আপনার পয়েন্টারের প্রয়োজন হয় তবে কেবল পয়েন্টারটি নিজেই রাখুন; এখানে কোনও সমস্যার সমাধান করার দরকার নেই
অয়ন টোডেরেল

10

টি এল; ডাঃ

এটি ব্যবহার করুন std::reference_wrapper:

#include <functional>
#include <string>
#include <vector>
#include <iostream>

int main()
{
    std::string hello = "Hello, ";
    std::string world = "everyone!";
    typedef std::vector<std::reference_wrapper<std::string>> vec_t;
    vec_t vec = {hello, world};
    vec[1].get() = "world!";
    std::cout << hello << world << std::endl;
    return 0;
}

Demo

দীর্ঘ উত্তর

হিসাবে মান প্রস্তাব দেওয়া , একটি প্রমিত ধারক জন্য Xধরনের বস্তু ধারণকারী T, Tহতে হবে Erasableথেকে X

Erasable এর মানে হল যে নীচের প্রকাশটি ভালভাবে গঠিত:

allocator_traits<A>::destroy(m, p)

Aকনটেইনার এর বরাদ্দকারী টাইপ, mবরাদ্দ উদাহরণ এবং pটাইপ একটি পয়েন্টার হয় *T। সংজ্ঞা জন্য এখানে দেখুন Erasable

ডিফল্টরূপে, std::allocator<T>ভেক্টরের বরাদ্দকারী হিসাবে ব্যবহৃত হয়। ডিফল্ট বরাদ্দকারী সহ, প্রয়োজনীয়তা এর বৈধতার সমতুল্য p->~T()(নোটটি Tএকটি রেফারেন্স টাইপ এবং pএকটি রেফারেন্সের দিকে নির্দেশক)। যাহোক, একটি রেফারেন্সের পয়েন্টারটি অবৈধ , সুতরাং এক্সপ্রেশনটি ভালভাবে গঠিত হয় না।


3

অন্যরা যেমন উল্লেখ করেছে, আপনি সম্ভবত এর পরিবর্তে পয়েন্টারগুলির একটি ভেক্টর ব্যবহার করে শেষ করবেন।

যাইহোক, আপনি পরিবর্তে একটি ptr_vector ব্যবহার বিবেচনা করতে পারেন !


4
এই উত্তরটি কার্যকর হয় না, যেহেতু একটি পিটিআর_ভেক্টর একটি সঞ্চয়স্থান হওয়ার কথা। এটি এটি সরানোর সময় পয়েন্টারগুলি মুছে ফেলবে। সুতরাং এটি তাঁর উদ্দেশ্যে ব্যবহারযোগ্য নয়।
ক্লিমেন্স মরজেন্সটারন

0

অন্যান্য মতামত হিসাবে, আপনি পয়েন্টার ব্যবহারের মধ্যে সীমাবদ্ধ। তবে যদি এটি সহায়তা করে তবে পয়েন্টারগুলির সাথে সরাসরি মুখোমুখি হওয়া এড়াতে এখানে একটি কৌশল।

আপনি নিম্নলিখিত মত কিছু করতে পারেন:

vector<int*> iarray;
int default_item = 0; // for handling out-of-range exception

int& get_item_as_ref(unsigned int idx) {
   // handling out-of-range exception
   if(idx >= iarray.size()) 
      return default_item;
   return reinterpret_cast<int&>(*iarray[idx]);
}

reinterpret_castপ্রয়োজন নেই
Xeverous

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