c++ - أفضل طريقة لإلحاق ناقلات للمتجه




c++11 vector (3)

std::vector<int> a;
std::vector<int> b;
std::vector<int> c;

أرغب في تسلسل هذه المتجهات الثلاثة بإلحاق عناصر b و c إلى. ما هي أفضل طريقة للقيام بذلك ، ولماذا؟

1) باستخدام vector::insert :

a.reserve(a.size() + b.size() + c.size());
a.insert(a.end(), b.begin(), b.end());
a.insert(a.end(), c.begin(), c.end());
b.clear();
c.clear();

2) باستخدام std::copy :

a.reserve(a.size() + b.size() + c.size());
std::copy(b.begin(), b.end(), std::inserter(a, a.end()));
std::copy(c.begin(), c.end(), std::inserter(a, a.end()));
b.clear();
c.clear();

3) باستخدام std::move (من C++11 ):

a.reserve(a.size() + b.size() + c.size());
std::move(b.begin(), b.end(), std::inserter(a, a.end()));
std::move(c.begin(), c.end(), std::inserter(a, a.end()));
b.clear();
c.clear();

إذا افترضنا أنك تريد نسخها وعدم تحريكها ، فستكون هذه أفضل طريقة:

a.reserve(a.size()+b.size()+c.size()); // Reserve space first
a.insert(a.end(),b.begin(),b.end());
a.insert(a.end(),c.begin(),c.end());

إذا كنت ترغب في الانتقال:

a.reserve(a.size()+b.size()+c.size()); // Reserve space first
a.insert(a.end(),std::make_move_iterator(b.begin()),
         std::make_move_iterator(b.end()));
a.insert(a.end(),std::make_move_iterator(c.begin()),
         std::make_move_iterator(c.end()));
b.swap(std::vector<int>()); // Clear and deallocate space
c.swap(std::vector<int>()); // Clear and deallocate space

تحديث : لقد قمت بتحرير سؤالك عدة مرات الآن لجعله مستهدفًا إلى حد ما. الخيار الأول هو الآن مشابه جدًا لاقتراحي الأول.

التحديث 2 : اعتبارًا من C ++ 11 ، قد لا يكون عليك استخدام خدعة "المقايضة مع المتجه الفارغ" لمسح المساحة وإلغاء تخصيصها ، اعتمادًا على تنفيذ المكتبة vector . ما يلي قد يؤدي المهمة بطريقة أكثر سهولة:

// Empty the vectors of objects
b.clear(); 
c.clear();

// Deallocate the memory allocated by the vectors 
// Note: Unlike the swap trick, this is non-binding and any space reduction
//       depends on the implementation of std::vector
b.shrink_to_fit();
c.shrink_to_fit();

إذا كنت تريد بالفعل إلحاق بيانات b و c في المتجه a ، فيجب عليك القيام بالإدراج (وهو في الواقع 1. ):

a.reserve( a.size() + b.size() + c.size() ); // preallocate memory (see why)
a.insert( a.end(), b.begin(), b.end() );
a.insert( a.end(), c.begin(), c.end() );

اعتمادًا على المترجم std::copy (your 2. ) يجب أن يكون عادة سريعًا.

نظرًا لأن std::vector دائمًا ما يكون متجاورًا في الذاكرة ، فلا يمكنك التحرك فقط (كما هو موضح في C ++ 11) وإذا كنت تعرف حجم النهاية ، فعليك بحجز متجهك (سيؤدي ذلك إلى تجنب إعادة تخصيص غير ضروري قوه موجهة). ولكن إذا كنت تقلق حقا بشأن الأداء ، دع هذا std::vector وقم بالتكرار فوقها عندما تضطر إلى قراءة بياناتها.


في رأيي ، الحل الأول هو أفضل طريقة للذهاب.

vector<>::insert لإضافة عنصر بحيث يكون الحل الأنسب.

يمكنك استدعاء reserve على متجه الوجهة لحجز بعض المساحة ، ولكن ما لم تقم بإضافة الكثير من المتجهات معًا ، فمن المرجح أنها لن تقدم الكثير من الفوائد: vector<>::insert تعرف عدد العناصر التي ستتم إضافتها ، ستتجنب فقط مكالمة reserve واحدة.

ملاحظة : إذا كانت هذه vector لنوع أكثر تعقيدًا (أي فئة مخصصة ، أو حتى std::string ) ، فإن استخدام std::move قد يوفر لك تحسينًا في الأداء ، لأنه قد يتجنب منشئ النسخ. ومع ذلك ، لن يعطيك أي فوائد.

ملاحظة 2 : تجدر الإشارة إلى أن استخدام std::move سوف يجعل محتوى vector المصدر الخاص بك غير قابل للاستخدام.







std