এসটিডি :: ভেক্টর :: অদলবদল পদ্ধতি ব্যবহার করে সি ++ তে দুটি পৃথক ভেক্টর অদলবদল করা কি নিরাপদ?


30

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

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

int main()
{
    std::vector<std::string> First{"example", "second" , "C++" , "Hello world" };
    std::vector<std::string> Second{"Hello"};

    First.swap(Second);

    for(auto a : Second) std::cout << a << "\n";
    return 0;
}

কল্পনা করুন যে ভেক্টরটি নেই std::string, তবুও ক্লাসগুলি:

std::vector<Widget> WidgetVector;

std::vector<Widget2> Widget2Vector;

std::vector::swapপদ্ধতিটির সাহায্যে দুটি ভেক্টরকে অদলবদল করা কি এখনও নিরাপদ : WidgetVector.swap(Widget2Vector);বা এটি কোনও ইউবির দিকে পরিচালিত করবে?

উত্তর:


20

এটি নিরাপদ কারণ অদলবদলের ক্রিয়াকলাপের সময় কিছুই তৈরি হয়নি। কেবল শ্রেণীর ডেটা সদস্যদেরই std::vectorঅদলবদল করা হয়।

নিম্নলিখিত বিক্ষোভমূলক প্রোগ্রামটি বিবেচনা করুন যা ক্লাসের অবজেক্টগুলিকে কীভাবে std::vectorঅদলবদল করা যায় তা তা পরিষ্কার করে দেয় ।

#include <iostream>
#include <utility>
#include <iterator>
#include <algorithm>
#include <numeric>

class A
{
public:
    explicit A( size_t n ) : ptr( new int[n]() ), n( n )
    {
        std::iota( ptr, ptr + n, 0 );   
    }

    ~A() 
    { 
        delete []ptr; 
    }

    void swap( A & a ) noexcept
    {
        std::swap( ptr, a.ptr );
        std::swap( n, a.n );
    }

    friend std::ostream & operator <<( std::ostream &os, const A &a )
    {
        std::copy( a.ptr, a.ptr + a.n, std::ostream_iterator<int>( os, " " ) );
        return os;
    }

private:    
    int *ptr;
    size_t n;
};

int main() 
{
    A a1( 10 );
    A a2( 5 );

    std::cout << a1 << '\n';
    std::cout << a2 << '\n';

    std::cout << '\n';

    a1.swap( a2 );

    std::cout << a1 << '\n';
    std::cout << a2 << '\n';

    std::cout << '\n';

    return 0;
}

প্রোগ্রাম আউটপুট হয়

0 1 2 3 4 5 6 7 8 9 
0 1 2 3 4 

0 1 2 3 4 
0 1 2 3 4 5 6 7 8 9 

আপনি কেবল ডেটা সদস্য দেখেন ptrএবং nসদস্য ফাংশন অদলবদল হয়। অতিরিক্ত সংস্থান ব্যবহার করা হয় না।

ক্লাসে অনুরূপ পন্থা ব্যবহৃত হয় std::vector

এই উদাহরণ হিসাবে

std::vector<Widget> WidgetVector;

std::vector<Widget2> Widget2Vector;

তারপরে বিভিন্ন শ্রেণীর বস্তু রয়েছে। সদস্য ফাংশন অদলবদল একই ধরণের ভেক্টরগুলিতে প্রয়োগ করা হয়।


6
তবে ওপি'র আসল কেস, যেখানে ভেক্টরগুলি অদলবদল করা হচ্ছে তা বিভিন্ন শ্রেণীর?
অ্যাড্রিয়ান মোল

4
@ অ্যাড্রিয়ানমোল প্রদত্ত ধরণের ভেক্টরের জন্য সংজ্ঞায়িত হলে সদস্য ফাংশন অদলবদল করে। এটি বিভিন্ন ধরণের ভেক্টরগুলির জন্য সংজ্ঞায়িত করা হয় না। এটি কোনও টেম্পলেট সদস্য ফাংশন নয়।
মস্কো থেকে

"একই ধরণের ভেক্টরগুলিতে" অদলবদল প্রয়োগ করা হয় "আপনার" একটি "কেবল" এর "এবং" প্রয়োগ "এর মধ্যে একটি" যুক্ত "করা উচিত।
এসএস অ্যান

অবশ্যই, রাষ্ট্রীয় বরাদ্দকারী জিনিস পরিবর্তন করতে পারে।
Deduplicator

21

হ্যাঁ, এটি একই ধরণের ভেক্টরদের অদলবদল করতে পুরোপুরি নিরাপদ।

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

বিভিন্ন ধরণের ভেক্টর ব্যবহার করে অদলবদল করা যাবে না swap। রূপান্তর এবং অদলবদল করে এমন আপনাকে নিজের ফাংশনটি প্রয়োগ করতে হবে।


3
আপনাকে প্রশ্নের দ্বিতীয় অংশটি আরও নিবিড়ভাবে দেখতে হবে।
মার্ক

নিবন্ধন করুন মিস 2। আপডেট করা হয়েছে।
নাথানঅলিভার

13

এসটিডি :: ভেক্টর :: অদলবদল পদ্ধতি ব্যবহার করে সি ++ তে দুটি পৃথক ভেক্টর অদলবদল করা কি নিরাপদ?

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

এখনও কি দুটি ভেক্টরকে স্ট্যান্ড :: ভেক্টর :: অদলবদল পদ্ধতি: উইজেটভেক্টর.স্বেপ (উইজেট 2 ভেক্টর) দিয়ে অদলবদল করা নিরাপদ; বা এটি একটি ইউবি হতে হবে?

সেখানে ইউবি থাকবে না। হ্যাঁ, প্রোগ্রামটি দুর্গঠিত এই অর্থে এটি এখনও নিরাপদ।


7

swapফাংশন অনুসরণ হিসাবে সংজ্ঞায়িত করা হয়: void swap( T& a, T& b );। এখানে নোট করুন যে উভয় aএবং একই ধরণেরb (এবং থাকতে হবে) । (এই স্বাক্ষরের সাথে সংজ্ঞায়িত এমন কোনও ফাংশন নেই: এটি কোনও অর্থবহ হবে না!)void swap( T1& a, T2& b )

একইভাবে, শ্রেণীর swap()সদস্য ফাংশনটি std::vectorনিম্নলিখিত হিসাবে সংজ্ঞায়িত করা হয়:

template<class T1> class vector // Note: simplified from the ACTUAL STL definition
{
//...
public:
    void swap( vector& other );
//...
};

এখন, ফাংশন প্যারামিটারের জন্য কোনও টেমপ্লেট ওভাররাইডের সাথে ( ফাংশন টেম্পলেটগুলির স্পষ্ট স্পেশালাইজেশনগুলি দেখুন ) সাথে কোনও 'সমতুল্য' সংজ্ঞা নেই template <typename T2> void swap(std::vector<T2>& other), সেই প্যারামিটারটি অবশ্যই একই ধরণের (টেমপ্লেট) ভেক্টর হতে হবে 'কলিং' শ্রেণি (এটি অবশ্যই একটি হতে হবে vector<T1>)।

তোমার std::vector<Widget>এবং std::vector<Widget2>দুটি ভিন্ন , ধরন, যাতে থেকে কল swap, কম্পাইল হবে কিনা (যেমন আপনার কোড আছে) হয় বস্তুর সদস্য ফাংশন ব্যবহার করতে চেষ্টা করুন, অথবা ব্যবহার বিশেষজ্ঞতা এর std::swap()ফাংশন যে দুটি লাগে std:vectorপরামিতি হিসেবে বস্তু।


8
std::vector::swapএটি একটি সদস্য ফাংশন, কীভাবে এটি একটি ফ্রি-স্ট্যান্ডিং টেম্পলেট ফাংশনটির বিশেষীকরণ হতে পারে ???
অ্যাকোনকাগুয়া

1
সঠিক ফলাফল, ভুল যুক্তি।
নাথানঅলিভার

2
@ অ্যাড্রিয়ানমোলের জন্য বিশেষায়নের অস্তিত্ব থাকার সময় std::swap, ওপি এটি ব্যবহার করছে না। আপনি যখন করেন First.swap(Second);, আপনি কল করেন std::vector::swapযা কোনও আলাদা ফাংশনstd::swap
নাথানঅলিভার

1
দুঃখিত, আমার খারাপ ... আপনার লিঙ্কটি সরাসরি ভেক্টরদের জন্য স্ট্যান্ড :: অদলবদলের বিশেষায়নের ডকুমেন্টেশনে যায়। তবে এটি সদস্য ফাংশন থেকে পৃথক , যা পাশাপাশি বিদ্যমান এবং প্রশ্নে ব্যবহৃত হয় (কেবল)।
অ্যাকোনকাগুয়া

2
যুক্তি আসলে আসলে সাদৃশ্যপূর্ণ: সদস্যটিকে void swap(std::vector& other)(যেমন std::vector<T>) হিসাবে সংজ্ঞায়িত করা হয়, ( template <typename U> void swap(std::vector<U>& other)ভ্যাক্টর নিজেই টি টি টাইপ প্যারামিটার ধরে নিচ্ছেন না) হিসাবে সংজ্ঞায়িত হয় ।
অ্যাকনকাগুয়া

4

আপনি দুটি ভিন্ন ধরণের ভেক্টরকে অদলবদল করতে পারবেন না তবে এটি ইউবির পরিবর্তে সংকলন ত্রুটি। vector::swapকেবল একই ধরণের ভেক্টর এবং বরাদ্দকারী গ্রহণ করে।

এটি কাজ করবে কিনা তা নিশ্চিত নয়, তবে আপনি যদি Widget2এস থেকে রূপান্তরিত এসযুক্ত ভেক্টর চান তবে আপনি এটি Widgetচেষ্টা করতে পারেন:

std::vector<Widget2> Widget2Vector(
    std::make_move_iterator(WidgetVector.begin()),
    std::make_move_iterator(WidgetVector.end())
);

Widget2থেকে গঠনমূলক পদক্ষেপ নিতে হবে Widget


0

using std::swap; swap(a, b);এবং a.swap(b);ঠিক একই শব্দার্থবিদ্যা যেখানে পরবর্তীকালে কাজ করে; কমপক্ষে কোনও বুদ্ধিমান টাইপের জন্য। সমস্ত মান প্রকারভেদে বিবেচনা করা হয়।

আপনি যদি কোনও আকর্ষণীয় বরাদ্দ ব্যবহার না করেন (অর্থাত্ রাষ্ট্রীয়, সর্বদা সমান নয়, এবং ধারক অদলবদলে প্রচারিত হয় না, দেখুন std::allocator_traits), std::vectorএকই টেমপ্লেট-আর্গুমেন্টের সাহায্যে দুটি সকে অদলবদল করা কেবলমাত্র তিনটি মানের একটি বিরক্তিকর অদলবদল (ক্ষমতা, আকার এবং ডেটা- পয়েন্টার)। এবং মৌলিক ধরণের অদলবদল, অনুপস্থিত ডাটা-রেসগুলি নিরাপদ এবং নিক্ষেপ করতে পারে না।

এমনকি এটি মান দ্বারা গ্যারান্টিযুক্ত। দেখুন std::vector::swap()

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