क्या मैं std :: वेक्टर को सूचीबद्ध कर सकता हूं- तत्वों के पूर्ण अग्रगमन के साथ वेक्टर?


14

मैंने उस समग्र सूची पर ध्यान दिया एसटीडी की initalization :: वेक्टर प्रदर्शन प्रारंभ कॉपी जब चाल अधिक लागू है। एक ही समय में, कई emplace_backs मुझे क्या चाहिए।

मैं केवल एक टेम्पलेट फ़ंक्शन लिखने के इस अपूर्ण समाधान के साथ आ सकता हूं init_emplace_vector। यह केवल गैर-स्पष्ट एकल-मूल्य के लिए इष्टतम है निर्माणकर्ताओं के , हालांकि।

template <typename T, typename... Args>
std::vector<T> init_emplace_vector(Args&&... args)
{
  std::vector<T> vec;
  vec.reserve(sizeof...(Args));  // by suggestion from user: eerorika
  (vec.emplace_back(std::forward<Args>(args)), ...);  // C++17
  return vec;
}

सवाल

क्या मुझे वास्तव में stel को आरंभ करने के लिए emplace_back का उपयोग करने की आवश्यकता है :: यथासंभव कुशलता से वेक्टर?

// an integer passed to large is actually the size of the resource
std::vector<large> v_init {
  1000,  // instance of class "large" is copied
  1001,  // copied
  1002,  // copied
};

std::vector<large> v_emplaced;
v_emplaced.emplace_back(1000);  // moved
v_emplaced.emplace_back(1001);  // moved
v_emplaced.emplace_back(1002);  // moved

std::vector<large> v_init_emplace = init_emplace_vector<large>(
  1000,   // moved
  1001,   // moved
  1002    // moved
);

उत्पादन

क्लास largeकॉपी / मूव्स (नीचे कार्यान्वयन) और इसलिए मेरे प्रोग्राम का आउटपुट के बारे में जानकारी देता है:

- initializer
large copy
large copy
large copy
- emplace_back
large move
large move
large move
- init_emplace_vector
large move
large move
large move

बड़े वर्ग का कार्यान्वयन

मेरा कार्यान्वयन largeकेवल एक प्रतिलिपि योग्य / चल प्रकार है जो एक बड़े संसाधन को रखता है जो प्रतिलिपि / चाल पर चेतावनी देता है।

struct large
{
  large(std::size_t size) : size(size), data(new int[size]) {}

  large(const large& rhs) : size(rhs.size), data(new int[rhs.size])
  {
    std::copy(rhs.data, rhs.data + rhs.size, data);
    std::puts("large copy");
  }

  large(large&& rhs) noexcept : size(rhs.size), data(rhs.data)
  {
    rhs.size = 0;
    rhs.data = nullptr;
    std::puts("large move");
  }

  large& operator=(large rhs) noexcept
  {
    std::swap(*this, rhs);
    return *this;
  }

  ~large() { delete[] data; }

  int* data;
  std::size_t size;
};

संपादित करें

रिजर्व का उपयोग करके, कोई प्रतिलिपि या चाल नहीं है। केवल large::large(std::size_t)कंस्ट्रक्टर को लगाया जाता है। सच्ची भावना।


1
यह एग्रीगेट-इनिशियलाइज़ेशन नहीं है, आप कंस्ट्रक्टर को कॉल कर रहे हैं जो कि लेता है std::initializer_list
सुपर

std :: वेक्टर के कंस्ट्रक्टर्स एक भ्रामक गड़बड़ IMHO हैं, और अगर मैं होता तो मैं वास्तव में इसमें शामिल होने से बचता अगर मैं बिल्कुल नहीं होता। इसके अलावा, यदि आप जानते हैं कि आप पहले से ही वैक्टर की सामग्री (जो ऐसा लगता है कि मामला हो सकता है) - एक पर विचार करें std::array
ईनपोकलम

1
एक operator=जो स्रोत को नष्ट कर देता काफी असामान्य है और अप्रत्याशित समस्याएं पैदा कर सकता है।
alain

1
init_emplace_vectorके साथ सुधार किया जा सकता हैvec.reserve(sizeof...(Args))
इंडियाना केर्निक

1
@alain operator=स्रोत को नष्ट नहीं करता है। यह कॉपी-स्वैप मुहावरा है।
reconn

जवाबों:


11

क्या मैं एसटीडी-वेक्टर को एग्रीगेट कर सकता हूं ...

नहीं std::vector, एक समुच्चय नहीं है, इसलिए इसे कुल-आरंभ नहीं किया जा सकता है।

आप इसके बजाय सूची-प्रारंभिककरण का अर्थ कर सकते हैं:

क्या मैं [सूची-आरंभ] एसटीडी :: वेक्टर तत्वों के पूर्ण अग्रेषण के साथ कर सकता हूं ?

सूची सूची-आरम्भ std::initializer_listनिर्माणकर्ता का उपयोग करता है और std::initializer_listउसके तर्कों की प्रतिलिपि बनाता है।

आपका init_emplace_vectorएक सभ्य समाधान प्रतीत होता है, हालांकि तत्वों को विस्थापित करने से पहले मेमोरी को जलाकर इसे बेहतर बनाया जा सकता है।


1
मुझे सही करने के लिए धन्यवाद। उसे संपादित। रिजर्व के साथ अच्छी बात है।
reconn
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.