ভেক্টর castালাইয়ের ভেক্টরের অপরিজ্ঞাত আচরণ


19

এই কোডটি আপাতদৃষ্টিতে অস্বীকারহীন পূর্ণসংখ্যার একটি অপরিজ্ঞাত সংখ্যা কেন লিখবে?

#include <iostream>
#include <vector>
using namespace std;


int main()
{
    for (int i : vector<vector<int>>{{77, 777, 7777}}[0])
        cout << i << ' ';
}

আমি আশা করেছিলাম আউটপুট হবে 77 777 7777

এই কোডটি কি অপরিবর্তিত থাকার কথা?

উত্তর:


18

vector<vector<int>>{{77, 777, 7777}}একটি অস্থায়ী এবং তারপরে vector<vector<int>>{{77, 777, 7777}}[0]রেঞ্জ-এর জন্য ব্যবহার করা হবে একটি অপরিজ্ঞাত আচরণ।

আপনার প্রথমে একটি ভেরিয়েবল তৈরি করা উচিত

#include <iostream>
#include <vector>
using namespace std;


int main()
{
    auto v = vector<vector<int>>{{77, 777, 7777}};
    for(int i: v[0])
        cout << i << ' ';
}

এছাড়াও যদি আপনি কলঙ্ক 10.0.0 ব্যবহার করেন তবে এটি এই আচরণ সম্পর্কে সতর্কতা দেয়।

সতর্কতা: পয়েন্টারটির ব্যাকিংকে পূর্ণ-এক্সপ্রেশন [-Wangangling-gsl] ভেক্টর> {{77, 777, 7777} 0 [0] এর শেষে ধ্বংস করা হবে


2
এই খারাপ অভ্যাসটি ছড়িয়ে পড়ার জন্য দয়া করে using std::vectorপরিবর্তে ব্যবহার করুন using namespace std;
ইনফিনিটিজারো

10

এটি কারণ যে ভেক্টরটি আপনি পুনরাবৃত্তি করছেন তা লুপে প্রবেশের আগে ধ্বংস হয়ে যাবে।

সাধারণত এটি ঘটে:

auto&& range = vector<vector<int>>{{77, 777, 7777}}[0];
auto&& first = std::begin(range);
auto&& last = std::end(range);
for(; first != last; ++first)
{
    int i = *first;
    // the rest of the loop
}

সমস্যাগুলি প্রথম লাইনে শুরু হয় কারণ এটি নিম্নলিখিত হিসাবে মূল্যায়ন করা হয়:

  1. প্রথমে প্রদত্ত যুক্তি দিয়ে ভেক্টরের ভেক্টর তৈরি করুন এবং ভেক্টর অস্থায়ী হয়ে যায় কারণ এর কোনও নাম নেই।

  2. তারপরে পরিসীমা রেফারেন্সটি সাবস্ক্রিপড ভেক্টরের সাথে আবদ্ধ, যা কেবলমাত্র ভেক্টর সহ এটির বৈধ হবে it

  3. একবার সেমিকোলন পৌঁছে গেলে অস্থায়ী ভেক্টরটি ধ্বংস হয়ে যায় এবং এর ডেস্ট্রাক্টরে এটি সাবস্ক্রিপডভুক্ত কোনও সঞ্চিত ভেক্টরকে ধ্বংস করে ফেলতে পারে।

  4. আপনি ধ্বংস হওয়া ভেক্টরের একটি রেফারেন্স দিয়ে শেষ করবেন যা পুনরাবৃত্তি হবে।

এই সমস্যা এড়াতে দুটি সমাধান রয়েছে:

  1. লুপের আগে ভেক্টরটি ঘোষণা করুন যাতে এটির পরিধি শেষ না হওয়া অবধি স্থায়ী হয় যার মধ্যে লুপ অন্তর্ভুক্ত থাকে।

  2. সি ++ ২০ টি একটি init স্টেটমেন্ট নিয়ে আসে যা এই সমস্যাগুলি সমাধান করার জন্য সরবরাহ করা হয় এবং আপনি যদি লুপের পরে অবিলম্বে ভেক্টরটি ধ্বংস করতে চান তবে প্রথম পদ্ধতির চেয়ে ভাল:

    for (vector<vector<int>> vec{{77, 777, 7777}}; int i : vec[0])
    {
    }

এটি "সাধারণত" ঘটে যা হয় না। এই সঠিক আচরণ (প্লাসের যথাযথ স্কোপিং এবং নামকরণের বিষয়ে বিবেচনা) স্ট্যান্ডার্ড দ্বারা বাধ্যতামূলক, বিধি-বিধি অনুসারে।
কনরাড রুডল্ফ

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

টিআইএল সি ++ 20 সিনট্যাক্সের জন্য ঘোষণামূলক পরিসীমা। খুশি বা দুঃখী হবে কিনা তা নিশ্চিত নয়।
উইংসের সাথে গ্রহাণুগুলি

6
vector<vector<int>>{{77, 777, 7777}}[0]

আমি আশা করি এটি ঝুঁকছে।

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

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