উপাদানগুলির নিখুঁত ফরওয়ার্ডিংয়ের সাথে আমি কী স্ট্যান্ড :: ভেক্টরকে তালিকাভুক্ত করতে পারি?


14

আমি লক্ষ্য করেছি যে স্টাড :: ভেক্টর সামগ্রিক তালিকা সূচনা করার সময় নড়াচড়া আরও প্রযোজ্য হলে অনুলিপি শুরু করে । একই সময়ে, একাধিক এমপ্ল্যাস_ব্যাকগুলি আমি যা চাই তা করে।

আমি কেবলমাত্র একটি টেম্পলেট ফাংশন লেখার এই অসম্পূর্ণ সমাধানটি নিয়ে আসতে পারি 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;
}

প্রশ্ন

স্ট্যান্ড :: ভেক্টর যথাসম্ভব দক্ষতার সাথে আরম্ভ করার জন্য আমার কি সত্যিই এমপ্লেস_ব্যাক ব্যবহার করা দরকার ?

// 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::array
einpoklum

1
একটি operator=যা উৎস ধ্বংস করে বেশ অস্বাভাবিক এবং অপ্রত্যাশিত সমস্যা হতে পারে।
Alain

1
init_emplace_vectorএর মাধ্যমে উন্নতি করা যেতে পারেvec.reserve(sizeof...(Args))
ইন্ডিয়ানা কার্নিক

1
@ আলাইন উত্সটি operator=ধ্বংস করে না। এটি কপি-সোয়াপ আইডিয়াম।

উত্তর:


11

আমি কী স্টাড :: ভেক্টরকে একত্রিত করতে পারি ...

নং std::vectorসামগ্রিক নয়, সুতরাং এটি সমষ্টিগত-আরম্ভ করা যায় না।

পরিবর্তে আপনি তালিকা-সূচনা বলতে বলতে পারেন, সেই ক্ষেত্রে:

উপাদানসমূহের নিখুঁত ফরোয়ার্ডিংয়ের সাথে আমি কি [তালিকা-প্রাথমিককরণ] এসটিডি :: ভেক্টরকে পারি?

না। তালিকা-সূচনাটি std::initializer_listকনস্ট্রাক্টর ব্যবহার করে এবং std::initializer_listতার যুক্তিগুলি অনুলিপি করে।

আপনার init_emplace_vectorকাছে এটি একটি শালীন সমাধান বলে মনে হচ্ছে, যদিও উপাদানগুলিকে কমিয়ে দেওয়ার আগে স্মৃতি সংরক্ষণ করে এটি উন্নত করা যেতে পারে।


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