एसटीडी का उपयोग करना :: कच्ची मेमोरी पर दृश्य के रूप में वेक्टर


71

मैं एक बाहरी पुस्तकालय का उपयोग कर रहा हूं जो किसी बिंदु पर मुझे पूर्णांक और आकार के एक कच्चे सूचक को देता है।

अब मैं std::vectorइन मानों को कच्चे पॉइंटर्स के साथ एक्सेस करने के बजाय इन मानों को एक्सेस और संशोधित करना चाहता हूँ ।

यहाँ एक स्पष्ट उदाहरण दिया गया है जो बिंदु की व्याख्या करता है:

size_t size = 0;
int * data = get_data_from_library(size);   // raw data from library {5,3,2,1,4}, size gets filled in

std::vector<int> v = ????;                  // pseudo vector to be used to access the raw data

std::sort(v.begin(), v.end());              // sort raw data in place

for (int i = 0; i < 5; i++)
{
  std::cout << data[i] << "\n";             // display sorted raw data 
}

अपेक्षित उत्पादन:

1
2
3
4
5

इसका कारण यह है कि मुझे <algorithm>उस डेटा पर एल्गोरिदम (सॉर्टिंग, स्वैपिंग तत्व आदि) लागू करने की आवश्यकता है ।

पर दूसरी ओर है कि वेक्टर के आकार बदलने बदला जा कभी नहीं होगा, इसलिए push_back, erase, insertकाम करने के लिए है कि वेक्टर पर आवश्यकता नहीं है।

मैं लाइब्रेरी से डेटा के आधार पर एक वेक्टर का निर्माण कर सकता था, उस वेक्टर को संशोधित करने और डेटा को लाइब्रेरी में वापस कॉपी करने के लिए उपयोग कर सकता था, लेकिन यह दो पूर्ण प्रतियां होंगी जो मैं डेटा सेट से बचना चाहूंगा क्योंकि डेटा सेट वास्तव में बड़ा हो सकता है।


16
आप जो खोज रहे हैं वह एक काल्पनिक है std::vector_view, क्या आप नहीं हैं?
at ネ ロ 眠

3
@ @ Probably ネ ロ 眠 हां, शायद
Jabberwocky

5
यह कैसे std::vectorकाम करता है।
जेसपर जुहल


34
मानक एल्गोरिदम पुनरावृत्तियों पर काम करते हैं, और संकेत पुनरावृत्त होते हैं। आपको करने से कुछ भी नहीं रोक रहा है sort(arrayPointer, arrayPointer + elementCount);
विस्फ़ोटक - मोनिका

जवाबों:


60

समस्या यह है कि std::vectorआपको सरणी से तत्वों की एक प्रतिलिपि बनानी होगी जिसे आप इसे आरंभीकृत करते हैं क्योंकि इसमें उन वस्तुओं का स्वामित्व है जो इसमें शामिल हैं।

इससे बचने के लिए, आप एक सरणी के लिए एक स्लाइस ऑब्जेक्ट का उपयोग कर सकते हैं (जैसे कि क्या std::string_viewहै std::string)। आप अपने स्वयं के array_viewवर्ग टेम्पलेट कार्यान्वयन को लिख सकते हैं, जिनके उदाहरण कच्चे सूचक को किसी सरणी के पहले तत्व और सरणी लंबाई में ले जाकर निर्मित किए जाते हैं:

#include <cstdint>

template<typename T>
class array_view {
   T* ptr_;
   std::size_t len_;
public:
   array_view(T* ptr, std::size_t len) noexcept: ptr_{ptr}, len_{len} {}

   T& operator[](int i) noexcept { return ptr_[i]; }
   T const& operator[](int i) const noexcept { return ptr_[i]; }
   auto size() const noexcept { return len_; }

   auto begin() noexcept { return ptr_; }
   auto end() noexcept { return ptr_ + len_; }
};

array_viewएक सरणी संग्रहीत नहीं करता है; यह केवल सरणी की शुरुआत और उस सरणी की लंबाई के लिए एक संकेतक रखता है। इसलिए, array_viewवस्तुओं का निर्माण और प्रतिलिपि बनाना सस्ता है।

के बाद से array_viewप्रदान करता है begin()और end()सदस्य काम करता है, आप मानक पुस्तकालय एल्गोरिदम (जैसे, उपयोग कर सकते हैं std::sort, std::find, std::lower_boundउस पर, आदि):

#define LEN 5

auto main() -> int {
   int arr[LEN] = {4, 5, 1, 2, 3};

   array_view<int> av(arr, LEN);

   std::sort(av.begin(), av.end());

   for (auto const& val: av)
      std::cout << val << ' ';
   std::cout << '\n';
}

आउटपुट:

1 2 3 4 5

इसके बजाय std::span(या gsl::span) का उपयोग करें

उपरोक्त कार्यान्वयन टुकड़ा वस्तुओं के पीछे की अवधारणा को उजागर करता है । हालाँकि, C ++ 20 के बाद से आप std::spanइसके बजाय सीधे उपयोग कर सकते हैं । किसी भी स्थिति में, आप gsl::spanC ++ 14 के बाद से उपयोग कर सकते हैं ।


आपने तरीकों को noexcept के रूप में चिह्नित क्यों किया? आप बिल्कुल भी गारंटी नहीं दे सकते कि कोई अपवाद नहीं फेंका जा रहा है, क्या आप कर सकते हैं?
सोनांक्सो


@mooeeeeeep केवल एक लिंक की तुलना में कुछ स्पष्टीकरण छोड़ना बेहतर है। भविष्य में लिंक समाप्त हो सकता है जबकि मैंने देखा है कि यह बहुत हुआ।
जेसन लियू

63

सी ++ 20 के std::span

यदि आप C ++ 20 का उपयोग करने में सक्षम हैं, तो आप उपयोग कर सकते हैं std::spanजो एक पॉइंटर - लंबाई की जोड़ी है जो उपयोगकर्ता को तत्वों के एक सन्निहित अनुक्रम में एक दृश्य देता है। यह एक किसी प्रकार का है std::string_view, और जब तक दोनों std::spanऔर std::string_viewगैर मालिक विचार हैं, std::string_viewकेवल पढ़ने के लिए दृश्य है।

डॉक्स से:

क्लास टेम्प्लेट स्पैन एक ऑब्जेक्ट का वर्णन करता है जो ऑब्जेक्ट के एक सन्निहित अनुक्रम को स्थिति शून्य पर अनुक्रम के पहले तत्व के साथ संदर्भित कर सकता है। एक अवधि में या तो एक स्थिर सीमा हो सकती है, जिस स्थिति में अनुक्रम में तत्वों की संख्या ज्ञात होती है और प्रकार में एन्कोडेड होती है, या एक गतिशील सीमा होती है।

तो निम्नलिखित काम करेगा:

#include <span>
#include <iostream>
#include <algorithm>

int main() {
    int data[] = { 5, 3, 2, 1, 4 };
    std::span<int> s{data, 5};

    std::sort(s.begin(), s.end());

    for (auto const i : s) {
        std::cout << i << "\n";
    }

    return 0;
}

इसे लाइव देखें

चूंकि std::spanमूल रूप से पॉइंटर - लंबाई जोड़ी है, आप निम्न तरीके से भी उपयोग कर सकते हैं:

size_t size = 0;
int *data = get_data_from_library(size);
std::span<int> s{data, size};

नोट: सभी कंपाइलर समर्थन नहीं करते हैं std::spanयहां कंपाइलर सपोर्ट देखें ।

अपडेट करें

यदि आप C ++ 20 का उपयोग करने में सक्षम नहीं हैं, तो आप उपयोग कर सकते हैं gsl::spanजो मूल रूप से C ++ मानक का आधार संस्करण है std::span

सी ++ 11 समाधान

यदि आप C ++ 11 मानक तक सीमित हैं, तो आप अपने स्वयं के साधारण spanवर्ग को लागू करने का प्रयास कर सकते हैं :

template<typename T>
class span {
   T* ptr_;
   std::size_t len_;

public:
    span(T* ptr, std::size_t len) noexcept
        : ptr_{ptr}, len_{len}
    {}

    T& operator[](int i) noexcept {
        return *ptr_[i];
    }

    T const& operator[](int i) const noexcept {
        return *ptr_[i];
    }

    std::size_t size() const noexcept {
        return len_;
    }

    T* begin() noexcept {
        return ptr_;
    }

    T* end() noexcept {
        return ptr_ + len_;
    }
};

सी ++ 11 संस्करण को लाइव देखें


4
आप gsl::spanC ++ 14 और इसके बाद के संस्करण का उपयोग कर सकते हैं यदि आपका कंपाइलर लागू नहीं होता हैstd::span
Artyer

2
@Artyer मैं इसके साथ अपने उत्तर को अपडेट करूंगा। धन्यवाद
सरौता

29

चूंकि एल्गोरिथ्म-पुस्तकालय पुनरावृत्तियों के साथ काम करता है आप सरणी रख सकते हैं।

संकेत और ज्ञात सरणी लंबाई के लिए

यहां आप कच्चे पॉइंटर्स को पुनरावृत्तियों के रूप में उपयोग कर सकते हैं। वे सभी ऑप्रेशनों का समर्थन करते हैं जो एक इटरेटर समर्थन करता है (वेतन वृद्धि, समानता के लिए तुलना, आदि का मूल्य ...):

#include <iostream>
#include <algorithm>

int *get_data_from_library(int &size) {
    static int data[] = {5,3,2,1,4}; 

    size = 5;

    return data;
}


int main()
{
    int size;
    int *data = get_data_from_library(size);

    std::sort(data, data + size);

    for (int i = 0; i < size; i++)
    {
        std::cout << data[i] << "\n";
    }
}

dataपुनरावर्तक द्वारा वापस की तरह dirst सरणी सदस्य के लिए अंक begin()और data + sizeपुनरावर्तक द्वारा वापस की तरह सरणी के अंतिम तत्व के बाद तत्व को अंक end()

सरणियों के लिए

यहां आप उपयोग कर सकते हैं std::begin()औरstd::end()

#include <iostream>
#include <algorithm>

int main()
{
    int data[] = {5,3,2,1,4};         // raw data from library

    std::sort(std::begin(data), std::end(data));    // sort raw data in place

    for (int i = 0; i < 5; i++)
    {
        std::cout << data[i] << "\n";   // display sorted raw data 
    }
}

लेकिन ध्यान रखें कि यह केवल काम करता है, अगर dataएक सूचक को क्षय नहीं करता है, क्योंकि तब लंबाई की जानकारी गायब हो जाती है।


7
यह सही जवाब है। एल्गोरिदम श्रेणियों पर लागू होते हैं । कंटेनर (उदाहरण के लिए, std :: वेक्टर) प्रबंधन रेंज का एक तरीका है, लेकिन वे एकमात्र तरीका नहीं हैं।
पीट बेकर

13

आप कच्चे एरेज़ पर पुनरावृत्तियों को प्राप्त कर सकते हैं और उन्हें एल्गोरिदम में उपयोग कर सकते हैं:

    int data[] = {5,3,2,1,4};
    std::sort(std::begin(data), std::end(data));
    for (auto i : data) {
        std::cout << i << std::endl;
    }

यदि आप कच्चे पॉइंटर्स (ptr + size) के साथ काम कर रहे हैं, तो आप निम्न तकनीक का उपयोग कर सकते हैं:

    size_t size = 0;
    int * data = get_data_from_library(size);
    auto b = data;
    auto e = b + size;
    std::sort(b, e);
    for (auto it = b; it != e; ++it) {
        cout << *it << endl;
    }

UPD: हालाँकि, उपरोक्त उदाहरण खराब डिज़ाइन का है। पुस्तकालय हमें एक कच्चा सूचक देता है और हम नहीं जानते कि अंतर्निहित बफर कहाँ आवंटित किया गया है और इसे मुक्त करने वाला कौन है।

आमतौर पर, कॉलर फ़ंक्शन को डेटा भरने के लिए एक बफर प्रदान करता है। उस स्थिति में, हम वेक्टर का प्रचार कर सकते हैं और इसके अंतर्निहित बफर का उपयोग कर सकते हैं:

    std::vector<int> v;
    v.resize(256); // allocate a buffer for 256 integers
    size_t size = get_data_from_library(v.data(), v.size());
    // shrink down to actual data. Note that no memory realocations or copy is done here.
    v.resize(size);
    std::sort(v.begin(), v.end());
    for (auto i : v) {
        cout << i << endl;
    }

C ++ 11 या इसके बाद के संस्करण का उपयोग करते हुए हम वेक्टर वापस करने के लिए get_data_from_library () भी बना सकते हैं। संचालन को स्थानांतरित करने के लिए धन्यवाद, कोई मेमोरी कॉपी नहीं होगी।


2
फिर आप auto begin = data; auto end = data + size;
पुनरावृत्तियों के

हालाँकि, सवाल यह है कि डेटा कहाँ get_data_from_library()से आबंटित किया गया है? शायद हम इसे बिल्कुल भी नहीं बदलने वाले हैं। यदि हमें लाइब्रेरी में एक बफर पास करने की आवश्यकता है, तो हम वेक्टर आवंटित कर सकते हैं और पास कर सकते हैंv.data()
पूजा

1
@ डेटा लाइब्रेरी के स्वामित्व में है, लेकिन इसे बिना किसी प्रतिबंध के बदला जा सकता है (यह वास्तव में पूरे प्रश्न का बिंदु है)। केवल डेटा का आकार नहीं बदला जा सकता है।
Jabberwocky

1
@Jabberwocky ने डेटा को भरने के लिए वेक्टर के अंतर्निहित बफर का उपयोग करने के तरीके का एक बेहतर उदाहरण जोड़ा।
पूजा करें

9

आप std::vectorएक प्रतिलिपि बनाने के बिना ऐसा नहीं कर सकते । std::vectorसूचक के मालिक के पास यह हुड के नीचे है और आवंटित किए गए आवंटन के माध्यम से अंतरिक्ष आवंटित करता है।

यदि आपके पास एक संकलक है जो C ++ 20 के लिए समर्थन करता है, तो आप std :: span का उपयोग कर सकते हैं जो वास्तव में इस उद्देश्य के लिए बनाया गया था। यह एक पॉइंटर और आकार को "कंटेनर" में लपेटता है जिसमें C ++ कंटेनर इंटरफ़ेस होता है।

यदि नहीं, तो आप gsl :: span का उपयोग कर सकते हैं, जो मानक संस्करण बंद था।

यदि आप किसी अन्य पुस्तकालय का आयात नहीं करना चाहते हैं, तो आप अपने आप को इस बात के लिए लागू कर सकते हैं कि आप क्या कार्यक्षमता चाहते हैं।


9

अब मैं std :: वेक्टर का उपयोग करना चाहूंगा और इन मानों को संशोधित करूंगा

आप नहीं कर सकते। जो है, उसके लिए नहीं std::vectorहै। std::vectorअपने स्वयं के बफर का प्रबंधन करता है, जिसे हमेशा एक आवंटनकर्ता से अधिग्रहित किया जाता है। यह कभी भी दूसरे बफर का स्वामित्व नहीं लेता है (एक ही प्रकार के अन्य वेक्टर को छोड़कर)।

दूसरी ओर, आपको भी इसकी आवश्यकता नहीं है क्योंकि ...

इसका कारण यह है कि मुझे उस डेटा पर एल्गोरिदम (सॉर्टिंग, स्वैपिंग तत्व आदि) लागू करने की आवश्यकता है।

वे एल्गोरिदम पुनरावृत्तियों पर काम करते हैं। एक सूचक एक सरणी के लिए एक पुनरावृत्ति है। आपको वेक्टर की आवश्यकता नहीं है:

std::sort(data, data + size);

फंक्शन टेम्प्लेट के विपरीत <algorithm>, कुछ टूल्स जैसे कि रेंज-फॉर, std::begin/ std::endऔर C ++ 20 रेंज सिर्फ पुनरावृत्तियों की एक जोड़ी के साथ काम नहीं करते हैं, हालांकि वे वैक्टर जैसे कंटेनरों के साथ काम करते हैं। पुनरावृत्त + आकार के लिए एक आवरण वर्ग बनाना संभव है जो एक सीमा के रूप में व्यवहार करता है, और इन उपकरणों के साथ काम करता है। C ++ 20 मानक पुस्तकालय में इस तरह के आवरण को पेश करेगा std::span:।


7

में std::spanआने के बारे में अन्य अच्छे सुझाव के अलावा और अपने स्वयं के (हल्के) वर्ग सहित, तब तक पहले से ही आसान है (कॉपी करने के लिए स्वतंत्र महसूस करें):gsl:spanspan

template<class T>
struct span {
    T* first;
    size_t length;
    span(T* first_, size_t length_) : first(first_), length(length_) {};
    using value_type = std::remove_cv_t<T>;//primarily needed if used with templates
    bool empty() const { return length == 0; }
    auto begin() const { return first; }
    auto end() const { return first + length; }
};

static_assert(_MSVC_LANG <= 201703L, "remember to switch to std::span");

यदि आप अधिक सामान्य श्रेणी अवधारणा में रुचि रखते हैं, तो विशेष नोट बूस्ट रेंज लाइब्रेरी : https://www.boost.org/doc/libs/1_60_0/libs/range/doc/html/range/ference/ /utilities/iterator_range.html

श्रेणी अवधारणाएं में भी आ जाएंगी


1
किस using value_type = std::remove_cv_t<T>;लिए है?
Jabberwocky

1
... और आप निर्माता को भूल गए span(T* first_, size_t length) : first(first), length(length) {};:। मैंने आपका उत्तर संपादित कर दिया।
Jabberwocky

@ जैबरवॉकी मैं केवल कुल आरंभ का उपयोग करता था। लेकिन कंस्ट्रक्टर ठीक है।
darune

1
@eerorika मुझे लगता है कि आप सही हैं, मैंने गैर-
कास्ट

1
using value_type = std::remove_cv_t<T>;मुख्य रूप से अगर (एक 'सीमा' का VALUE_TYPE प्राप्त करने के लिए) टेम्पलेट प्रोग्रामिंग के साथ प्रयोग किया जाता है की जरूरत है। यदि आप केवल पुनरावृत्तियों का उपयोग करना चाहते हैं, तो आप उसे छोड़ या हटा सकते हैं।
darune

6

आप वास्तव में इसके लिए लगभग उपयोग कर सकते हैंstd::vector , जो आप देखना चाहते हैं स्मृति के लिए एक पॉइंटर को वापस करने के लिए कस्टम आवंटनकर्ता कार्यक्षमता का दुरुपयोग करके। काम करने के लिए मानक की गारंटी नहीं होगी (पैडिंग, अलाइनमेंट, लौटे वैल्यूज़ को इनिशियलाइज़ करना; शुरुआती साइज़ को असाइन करते समय आपको दर्द उठाना होगा और नॉन-प्राइमरी के लिए भी आपको अपने कंस्ट्रक्टर को हैक करना होगा। ), लेकिन व्यवहार में मैं इसे पर्याप्त ट्विक्स दिए जाने की उम्मीद करूंगा।

कभी ऐसा तो कभी कोई। यह बदसूरत, आश्चर्य की बात है, hacky, और अनावश्यक है। मानक पुस्तकालय के एल्गोरिदम पहले से ही कच्चे सरणियों के साथ-साथ वैक्टर के साथ काम करने के लिए डिज़ाइन किए गए हैं। उस के विवरण के लिए अन्य उत्तर देखें।


1
हम्म, हाँ जो कि vectorकंस्ट्रक्टरों के साथ काम कर सकता है जो एक कंस्ट्रक्टर आर्ग के रूप में एक कस्टम एलोकेटर संदर्भ लेते हैं (न कि केवल एक टेम्पलेट पार्सल)। मुझे लगता है कि आपको एक एलिमिनेटर ऑब्जेक्ट की आवश्यकता होगी, जिसमें रनटाइम पॉइंटर वैल्यू थी, न कि एक टेम्प्लेट पैरामीटर के रूप में अन्यथा यह केवल कॉन्स्ट्रेक्स पतों के लिए काम कर सकता था। आपको सावधान रहना होगा कि vectorडिफ़ॉल्ट .resize()डेटा को ऑब्जेक्ट पर न जाने दें और मौजूदा डेटा को ओवरराइट करें; वेक्टर बनाम नॉन-ओनिंग स्पैन जैसे मालिक कंटेनर के बीच बेमेल है यदि आप .push_back आदि का उपयोग करना शुरू करते हैं तो बहुत बड़ा है
पीटर कॉर्ड्स

1
@PeterCordes मेरा मतलब है, चलो सीड को दफनाना नहीं है - आपको भी पागल होना पड़ेगा। मेरे दिमाग में, इस विचार के बारे में सबसे अजीब बात यह है कि आवंटनकर्ता इंटरफ़ेस में वह constructविधि शामिल है जिसकी आवश्यकता होगी ... मैं नहीं सोच सकता कि गैर-हैकी उपयोग के मामलों को प्लेसमेंट-नए की आवश्यकता होगी।
स्नेफेल

1
स्पष्ट उपयोग के मामले में समय बर्बाद करने वाले तत्वों से बचने के लिए है जो आप किसी अन्य तरीके से लिखने वाले हैं, जैसे कि resize()इससे पहले कि आप किसी ऐसी चीज़ का संदर्भ दें जो इसे शुद्ध आउटपुट के रूप में उपयोग करना चाहती है (उदाहरण के लिए रीड सिस्टम कॉल)। व्यवहार में कंपाइलर अक्सर उस मेमसेट या जो भी हो, को दूर नहीं करते हैं। या यदि आपके पास एक आवंटनकर्ता था जो प्री-ज़ीरो मेमोरी प्राप्त करने के लिए कॉलोक का उपयोग करता है, तो आप इसे std::vector<int>डिफ़ॉल्ट रूप से गंदा करने से भी बचा सकते हैं जब डिफ़ॉल्ट-निर्माण करने वाली वस्तुओं में ऑल-जीरो बिट पैटर्न होता है। En.cppreference.com/w/cpp/container/vector/vector
पीटर कॉर्ड्स

4

जैसा कि दूसरों ने बताया है, std::vectorअंतर्निहित मेमोरी (कस्टम आवंटनकर्ता के साथ खिलवाड़ करने की कमी) का उपयोग नहीं किया जाना चाहिए।

दूसरों ने भी c ++ 20 की अवधि की सिफारिश की है, हालांकि जाहिर है कि c ++ 20 की आवश्यकता है।

मैं स्पैन-लाइट स्पैन की सिफारिश करूंगा । उद्धरण के लिए यह उपशीर्षक है:

स्पाइट लाइट - C ++ 98, C ++ 11 और बाद में सिंगल-फाइल हेडर-ओनली लाइब्रेरी के लिए A C ++ 20-जैसे स्पैन

यह एक गैर-स्वामित्व और परिवर्तनशील दृश्य प्रदान करता है (जैसा कि आप तत्वों और उनके आदेश को म्यूट कर सकते हैं लेकिन उन्हें सम्मिलित नहीं कर सकते हैं) और जैसा कि उद्धरण में कहा गया है कि कोई निर्भरता नहीं है और अधिकांश संकलक पर काम करता है।

आपका उदाहरण:

#include <algorithm>
#include <cstddef>
#include <iostream>

#include <nonstd/span.hpp>

static int data[] = {5, 1, 2, 4, 3};

// For example
int* get_data_from_library()
{
  return data;
}

int main ()
{
  const std::size_t size = 5;

  nonstd::span<int> v{get_data_from_library(), size};

  std::sort(v.begin(), v.end());

  for (auto i = 0UL; i < v.size(); ++i)
  {
    std::cout << v[i] << "\n";
  }
}

प्रिंटों

1
2
3
4
5

यह भी उल्टा है अगर एक दिन आप c ++ 20 पर स्विच करते हैं, तो आपको इसे इसके nonstd::spanसाथ बदलने में सक्षम होना चाहिए std::span


3

आप std::reference_wrapperC ++ 11 के बाद से उपलब्ध का उपयोग कर सकते हैं :

#include <iostream>
#include <iterator>
#include <vector>
#include <algorithm>

int main()
{
    int src_table[] = {5, 4, 3, 2, 1, 0};

    std::vector< std::reference_wrapper< int > > dest_vector;

    std::copy(std::begin(src_table), std::end(src_table), std::back_inserter(dest_vector));
    // if you don't have the array defined just a pointer and size then:
    // std::copy(src_table_ptr, src_table_ptr + size, std::back_inserter(dest_vector));

    std::sort(std::begin(dest_vector), std::end(dest_vector));

    std::for_each(std::begin(src_table), std::end(src_table), [](int x) { std::cout << x << '\n'; });
    std::for_each(std::begin(dest_vector), std::end(dest_vector), [](int x) { std::cout << x << '\n'; });
}

2
यह डेटा की एक प्रति प्रदर्शित करता है, और यही वह है जो मैं बचना चाहता हूं।
Jabberwocky

1
@Jabberwocky यह डेटा कॉपी नहीं करता है। लेकिन यह वह नहीं है जो आपने प्रश्न में पूछा था।
एरोरिका

@eerorika std::copy(std::begin(src_table), std::end(src_table), std::back_inserter(dest_vector));निश्चित रूप dest_vectorसे लिए गए मूल्यों से भरता है src_table(IOW डेटा कॉपी किया जाता है dest_vector), इसलिए मुझे आपकी टिप्पणी नहीं मिली। क्या आप समझाएँगे?
Jabberwocky

@ जैबरवॉकी यह मूल्यों की नकल नहीं करता है। यह रेफर रैपर के साथ ithe वेक्टर को भरता है।
एरोरिका

3
@Jabberwocky पूर्णांक मानों के मामले में अधिक अक्षम है।
एरोरिका
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.