সি-স্টাইল অ্যারে থেকে স্টাড :: ভেক্টর কীভাবে শুরু করবেন?


174

std::vectorসি-স্টাইল অ্যারে থেকে আরম্ভ করার সস্তারতম উপায় কী ?

উদাহরণ: নিম্নলিখিত শ্রেণিতে আমার কাছে একটি রয়েছে vectorতবে বাইরের বিধিনিষেধের কারণে ডেটা সি-স্টাইল অ্যারে হিসাবে প্রেরণ করা হবে:

class Foo {
  std::vector<double> w_;
public:
  void set_data(double* w, int len){
   // how to cheaply initialize the std::vector?
}

স্পষ্টতই, আমি কল করতে পারি w_.resize()এবং তারপরে উপাদানগুলি লুপ করতে পারি , বা কল করতে পারি std::copy()। এর চেয়ে আরও ভাল কোন পদ্ধতি আছে কি?


11
সমস্যার ক্রুসটি হ'ল ভেক্টরের পক্ষে এটি জানার কোনও উপায় নেই যে একই বরাদ্দকারী আপনার সি-স্টাইল অ্যারে তৈরি করতে ব্যবহৃত হয়েছিল কিনা। যেমন ভেক্টরকে অবশ্যই তার নিজস্ব বরাদ্দকারী ব্যবহার করে মেমরি বরাদ্দ করতে হবে। অন্যথায় এটি কেবল অন্তর্নিহিত অ্যারে পরিবর্তন করতে পারে এবং এটি আপনার অ্যারের সাথে প্রতিস্থাপন করতে পারে।
অকার্যকর

উত্তর:


233

ভুলে যাবেন না যে আপনি পয়েন্টারগুলিকে পুনরুক্তি হিসাবে ব্যবহার করতে পারেন:

w_.assign(w, w + len);

3
এটি বাস্তবায়নের সমস্যার একটি গুণ। যেহেতু পুনরাবৃত্তিকারীদের ট্যাগ রয়েছে যা তাদের বিভাগগুলি নির্দিষ্ট করে, তাই একটি বাস্তবায়ন assignঅবশ্যই তাদের অনুকূলিত করতে ব্যবহার করতে বিনামূল্যে; কমপক্ষে ভিসি ++ এ, এটি সত্যই তা করে।
পাভেল মিনায়েভ

38
দ্রুত সমাধানটি স্ট্যান্ড করা যেতে পারে :: ভেক্টর <ডাবল> ডাব্লিউ_ (ডাব্লু, ডাব্লু + লেন);
জামাক

1
এটি 'w_' এর জন্য একটি নতুন নির্মিত স্টোরেজে উপাদানগুলি অনুলিপি করে; 'w_.data' 'ডাব্লু' তে নির্দেশ করবে না। আপনার এখনও 'ডাব্লু' অপসারণ করতে হবে। মালিকানার স্থানান্তর নেই
ইন্ডি 9000

1
এটি যদি শেষের অতীতের একটি উপাদান থাকে তবে এটি ঠিক হওয়া উচিত (ঠিক v.end()তেমনই একটি পুনরাবৃত্তি একইরূপে ভেক্টরের সাহায্যে প্রান্তটি দেখায়)) যদি আপনি একটি দৃser়তা পান, তবে অন্য কোথাও কিছু বন্ধ রয়েছে।
পাভেল মিনায়েভ

1
কেবল দ্রুত, যখন ভেক্টর সুযোগের বাইরে চলে যাবে তখন এটি অ্যারে মেমরিটি কমিয়ে দেবে?
অ্যাড্রিয়ান কোচ

41

আপনি ইনিশিয়াল শব্দটি ব্যবহার করেন তাই এটি অস্পষ্ট যদি এটি এককালীন অ্যাসাইনমেন্ট হয় বা একাধিকবার ঘটতে পারে।

আপনার যদি কেবলমাত্র এককালীন সূচনা প্রয়োজন, আপনি এটি কনস্ট্রাক্টারে রেখে দুটি পুনরুক্তি ভেক্টর কনস্ট্রাক্টর ব্যবহার করতে পারেন:

Foo::Foo(double* w, int len) : w_(w, w + len) { }

অন্যথায় পূর্বে প্রস্তাবিত হিসাবে অ্যাসাইন ব্যবহার করুন:

void set_data(double* w, int len)
{
    w_.assign(w, w + len);
}

1
আমার ক্ষেত্রে, অ্যাসাইনমেন্টটি বারবার ঘটবে।
ফ্রাঙ্ক

12

আপনি স্বয়ংক্রিয়ভাবে অ্যারের আকারটি 'শিখতে' পারবেন:

template<typename T, size_t N>
void set_data(const T (&w)[N]){
    w_.assign(w, w+N);
}

আশা করি, আপনি উপরের মতো ইন্টারফেসটি সেট_ডেটাতে পরিবর্তন করতে পারবেন। এটি এখনও সি-স্টাইল অ্যারেটিকে তার প্রথম যুক্তি হিসাবে স্বীকার করে। এটি কেবল রেফারেন্সের দ্বারা এটি নেওয়া হয়।


কিভাবে এটা কাজ করে

[আপডেট: আকার শেখার জন্য আরও বিস্তৃত আলোচনার জন্য এখানে দেখুন ]

এখানে আরও সাধারণ সমাধান:

template<typename T, size_t N>
void copy_from_array(vector<T> &target_vector, const T (&source_array)[N]) {
    target_vector.assign(source_array, source_array+N);
}

এটি কাজ করে কারণ অ্যারেটি রেফারেন্স-থেকে-অ্যারে হিসাবে পাস হচ্ছে। সি / সি ++ এ আপনি কোনও ক্রিয়া হিসাবে কোনও অ্যারে পাস করতে পারবেন না, পরিবর্তে এটি পয়েন্টারের ক্ষয়ে যাবে এবং আপনি আকারটি হারাবেন। তবে সি ++ এ আপনি অ্যারেতে একটি রেফারেন্স পাস করতে পারেন

রেফারেন্স সহ একটি অ্যারে পাস করার জন্য ধরণের হুবহু মিলে যায়। একটি অ্যারের আকার তার ধরণের একটি অংশ। এর অর্থ আমরা আমাদের জন্য আকারটি জানতে টেমপ্লেট প্যারামিটার এন ব্যবহার করতে পারি।

এটি কোনও ভেক্টরকে ফিরিয়ে দেয় এমন ফাংশনটি এমনকি সহজ হতে পারে। কার্যকর সংকলক অপ্টিমাইজেশান কার্যকর হিসাবে, এটি দেখতে এটির চেয়ে দ্রুত হওয়া উচিত।

template<typename T, size_t N>
vector<T> convert_array_to_vector(const T (&source_array)[N]) {
    return vector<T>(source_array, source_array+N);
}

1
শেষ নমুনায়, return { begin(source_array), end(source_array) };এটিও সম্ভব
এমএম

12

ঠিক আছে, পাভেল খুব কাছাকাছি ছিল, তবে এসি স্টাইল অ্যারে থেকে ক্রমিক ধারকটি আরম্ভ করার জন্য আরও সহজ এবং মার্জিত সমাধান রয়েছে।

তোমার ক্ষেত্রে:

w_ (array, std::end(array))
  • অ্যারে আমাদের অ্যারের শুরুতে একটি পয়েন্টার দেবে (এটির নামটি ধরেনি),
  • std :: end (অ্যারে) অ্যারের শেষের দিকে আমাদেরকে একটি পুনরুক্তি দেবে।

1
সি ++ এর কী কী সংস্করণ অন্তর্ভুক্ত?
ভ্লাদ

1
এটি কমপক্ষে সি ++ 98 এর পরে স্টডি :: ভেক্টরের অন্যতম নির্মাতা .... একে 'রেঞ্জ কনস্ট্রাক্টর' বলা হয়। cplusplus.com/references/vector/vector/vector এটি ব্যবহার করে দেখুন।
মুগুরেল

1
আরও স্বতন্ত্র সংস্করণটি হ'ল: w_ (std :: start (অ্যারে), std :: শেষ (অ্যারে)); (ভবিষ্যতে আপনি সি ++ ধারকটির জন্য একটি সি অ্যারে পরিবর্তন করতে পারেন)।
অ্যান্ড্রু রোমানভ

13
মনে মনে রাখবেন, এটি কেবল তখনই কাজ করে যদি আপনার কাছে আসল থাকে array(যার অর্থ সাধারণত আপনি কোনও বিশ্বব্যাপী বা স্থানীয় (বর্তমান ফাংশনে ঘোষিত) অ্যারে থেকে অনুলিপি করছেন)। ওপি-র ক্ষেত্রে, তিনি একটি পয়েন্টার এবং একটি দৈর্ঘ্য পাচ্ছেন, এবং এটি দৈর্ঘ্যের উপর উল্লিখিত না হওয়ার কারণে তারা একটি আকারের অ্যারে বা কোনও কিছুতে পয়েন্টার গ্রহণ করতে পরিবর্তন করতে পারে না, সুতরাং std::endকাজ করবে না।
শ্যাডোএ্যাঞ্জার

2
vectorওভারলোড হয় না operator(), সুতরাং এটি সংকলন করবে না। std::endপয়েন্টারে ডাকলে কোনও লাভ হয় না (প্রশ্নটি একটি পয়েন্টার এবং একটি পৃথক দৈর্ঘ্যের ভেরিয়েবল থেকে ভেক্টর বরাদ্দ করতে বলে)। আপনি কী প্রস্তাব দেওয়ার চেষ্টা করছেন সে সম্পর্কে আরও প্রসঙ্গ দেখানোর জন্য এটি আপনার উত্তরকে উন্নত করবে
এমএম

2

দ্রুত জেনেরিক উত্তর:

std::vector<double> vec(carray,carray+carray_size); 

বা নির্দিষ্ট প্রশ্ন:

std::vector<double> w_(w,w+len); 

উপরের ভিত্তিতে : ভুলে যাবেন না যে আপনি পয়েন্টারগুলিকে পুনরুক্তি হিসাবে ব্যবহার করতে পারেন


0

std::vector<double>::assignযাবার উপায়, কারণ এটি খুব সামান্য কোড । কিন্তু আসলে এটি কীভাবে কাজ করে? এটি কি পুনরায় আকার না দিয়ে কপি করে? এমএস এসটিএল বাস্তবায়নে আমি এটি ব্যবহার করি ঠিক তেমনটি করে।

আমি আশঙ্কা করছি আপনার প্রয়োগের (পুনরায়) আরম্ভ করার কোনও দ্রুত উপায় নেইstd::vector


যদি ভেক্টর এবং একটি অ্যারের মধ্যে ডেটা ভাগ করা যায়? এই ক্ষেত্রে আমাদের কিছু অনুলিপি করা দরকার?
ভ্লাদ

এটি একটি উত্তর বা একটি প্রশ্ন? এটি ইতিমধ্যে বিদ্যমান উত্তরগুলি কী নিয়ে আসে?
জিন-ফ্রান্সোইস ফ্যাব্রে

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