ใช้ std :: vector เป็นมุมมองในหน่วยความจำดิบ


71

ฉันใช้ไลบรารี่ภายนอกซึ่งในบางครั้งจะให้ตัวชี้แบบดิบแก่อาร์เรย์ของจำนวนเต็มและขนาด

ตอนนี้ฉันต้องการที่จะใช้std::vectorในการเข้าถึงและแก้ไขค่าเหล่านี้ในสถานที่แทนที่จะเข้าถึงพวกเขาด้วยตัวชี้แบบดิบ

นี่คือตัวอย่าง articifial ที่อธิบายถึงจุด:

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ใช่มั้ย
眠りネロク

3
@ 眠りネロクใช่อาจ
Jabberwocky

5
นั่นไม่ใช่วิธีการstd::vectorทำงาน
Jesper Juhl


34
อัลกอริธึมมาตรฐานทำงานกับตัววนซ้ำและพอยน์เตอร์เป็นตัววนซ้ำ sort(arrayPointer, arrayPointer + elementCount);ไม่มีอะไรที่หยุดคุณจากการทำ
cmaster - คืนสถานะโมนิกา

คำตอบ:


60

ปัญหาคือstd::vectorต้องทำสำเนาองค์ประกอบจากอาร์เรย์ที่คุณเริ่มต้นด้วยเนื่องจากมีความเป็นเจ้าของวัตถุที่มี

เพื่อหลีกเลี่ยงนี้คุณสามารถใช้ชิ้นวัตถุสำหรับอาร์เรย์ (เช่นคล้ายกับสิ่งที่std::string_viewเป็นไปstd::string) คุณสามารถเขียนarray_viewการประยุกต์ใช้แม่แบบคลาสของคุณเองซึ่งอินสแตนซ์ถูกสร้างขึ้นโดยการใช้ตัวชี้ raw ไปยังองค์ประกอบแรกของอาร์เรย์และความยาวของอาร์เรย์:

#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) แทน

การดำเนินการดังกล่าวข้างต้น exposes แนวคิดที่อยู่เบื้องหลังวัตถุชิ้น อย่างไรก็ตามตั้งแต่ C ++ 20 คุณสามารถใช้งานได้โดยตรงstd::spanแทน ไม่ว่าในกรณีใดคุณสามารถใช้gsl::spanตั้งแต่ C ++ 14


ทำไมคุณถึงทำเครื่องหมายวิธีการว่าเป็นข้อยกเว้น? คุณไม่สามารถรับประกันได้เลยว่าจะไม่มีข้อยกเว้นถูกโยนได้ไหม
SonneXo


@moooeeeep มันจะดีกว่าที่จะออกจากคำอธิบายมากกว่าแค่การเชื่อมโยง ลิงก์อาจหมดอายุในอนาคตในขณะที่ฉันเคยเห็นสิ่งนี้เกิดขึ้นมากมาย
Jason Liu

63

C ++ 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ไม่คอมไพเลอร์สนับสนุน ตรวจสอบการสนับสนุนคอมไพเลอร์ที่นี่

UPDATE

หากคุณไม่สามารถใช้ C ++ 20 ได้คุณสามารถใช้gsl::spanรุ่นพื้นฐานของมาตรฐาน C ++ std::spanได้

โซลูชัน C ++ 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_;
    }
};

ลองใช้ C ++ 11 เวอร์ชั่นสด


4
คุณสามารถใช้gsl::spanสำหรับ C ++ 14 ขึ้นไปหากคอมไพเลอร์ของคุณไม่ได้ติดตั้งstd::span
Artyer

2
@Artyer ฉันจะอัปเดตคำตอบของฉันด้วยสิ่งนี้ ขอบคุณ
NutCracker

29

เนื่องจากอัลกอริทึมไลบรารีทำงานร่วมกับตัววนซ้ำคุณสามารถเก็บอาร์เรย์ได้

สำหรับพอยน์เตอร์และความยาวของอาเรย์ที่รู้จัก

ที่นี่คุณสามารถใช้พอยน์เตอร์ดิบเป็นตัววนซ้ำ พวกเขาสนับสนุน opertations ทั้งหมดที่ iterator รองรับ (เพิ่มขึ้น, การเปรียบเทียบสำหรับความเสมอภาค, มูลค่า, ฯลฯ ... ):

#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 เช่น iterator กลับโดยbegin()และdata + sizeชี้ไปที่องค์ประกอบหลังจากองค์ประกอบสุดท้ายของอาร์เรย์เช่น iterator 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 :: vector) เป็นวิธีหนึ่งในการจัดการช่วง แต่มันไม่ใช่วิธีเดียว
Pete Becker

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_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;
PooSH

อย่างไรก็ตามคำถามคือตำแหน่งที่ข้อมูลถูกส่งคืนโดยการget_data_from_library()จัดสรร? บางทีเราไม่ควรเปลี่ยนเลย ถ้าเราต้องการส่งบัฟเฟอร์ไปยังไลบรารีเราสามารถจัดสรรเวกเตอร์และส่งได้v.data()
PooSH

1
@PooSH ข้อมูลเป็นของห้องสมุด แต่สามารถเปลี่ยนแปลงได้โดยไม่มีข้อ จำกัด (ที่จริงแล้วเป็นประเด็นของคำถามทั้งหมด) ขนาดของข้อมูลไม่สามารถเปลี่ยนแปลงได้
Jabberwocky

1
@Jabberwocky เพิ่มตัวอย่างที่ดีขึ้นของวิธีการใช้บัฟเฟอร์พื้นฐานของเวกเตอร์เพื่อเติมข้อมูลใน
PooSH

9

คุณไม่สามารถทำสิ่งนี้ได้std::vectorโดยไม่ใส่สำเนา std::vectorเป็นเจ้าของตัวชี้ที่อยู่ภายใต้ประทุนและจัดสรรพื้นที่ผ่านตัวจัดสรรที่ให้ไว้

หากคุณมี acess ให้กับคอมไพเลอร์ที่รองรับ C ++ 20 คุณสามารถใช้std :: spanซึ่งสร้างขึ้นเพื่อวัตถุประสงค์นี้ มันล้อมรอบตัวชี้และขนาดลงใน "คอนเทนเนอร์" ที่มีอินเทอร์เฟซคอนเทนเนอร์ C ++

หากไม่เป็นเช่นนั้นคุณสามารถใช้gsl :: spanซึ่งเป็นสิ่งที่เวอร์ชันมาตรฐานอ้างอิง

หากคุณไม่ต้องการนำเข้าห้องสมุดอื่นคุณสามารถนำสิ่งนี้ไปใช้ด้วยตัวคุณเองโดยขึ้นอยู่กับฟังก์ชันการทำงานทั้งหมดที่คุณต้องการ


9

ตอนนี้ฉันต้องการใช้ std :: vector เพื่อเข้าถึงและแก้ไขค่าเหล่านี้

คุณไม่สามารถ. นั่นไม่ใช่สิ่งที่std::vectorมีไว้สำหรับ std::vectorจัดการบัฟเฟอร์ของตัวเองซึ่งได้มาจากตัวจัดสรรเสมอ มันไม่เคยเป็นเจ้าของบัฟเฟอร์อื่น (ยกเว้นจากเวกเตอร์ชนิดเดียวกัน)

ในขณะที่คุณไม่จำเป็นต้องเพราะ ...

เหตุผลก็คือฉันจำเป็นต้องใช้อัลกอริทึมจาก (การเรียงลำดับการกวาดล้างองค์ประกอบ ฯลฯ ) กับข้อมูลนั้น

อัลกอริทึมเหล่านั้นทำงานกับตัววนซ้ำ ตัวชี้เป็นตัววนซ้ำไปยังอาร์เรย์ คุณไม่ต้องการเวกเตอร์:

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

<algorithm>เครื่องมือบางตัวเช่น range-for, std::begin/ std::endและ C ++ 20 ต่างจากเท็มเพลตฟังก์ชั่นที่ใช้งานไม่ได้กับ iterator เพียงคู่เดียวในขณะที่มันทำงานกับคอนเทนเนอร์เช่นเวกเตอร์ เป็นไปได้ที่จะสร้างคลาส wrapper สำหรับ iterator + size ที่ทำงานเป็นช่วงและทำงานกับเครื่องมือเหล่านี้ C ++ 20 std::spanจะแนะนำเสื้อคลุมดังกล่าวเข้าไปในห้องสมุดมาตรฐาน:


7

นอกจากข้อเสนอแนะที่ดีอื่น ๆ เกี่ยวกับการstd::spanมาในและgsl:spanรวมถึงspanคลาสของคุณเอง (น้ำหนักเบา) จนกระทั่งง่ายพออยู่แล้ว (อย่าลังเลที่จะคัดลอก):

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/reference /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

@ Jabberwocky ฉันเพิ่งใช้การเริ่มต้นรวม แต่ตัวสร้างเป็นเรื่องปกติ
darune

1
@eerorika ฉันเดาว่าคุณพูดถูกฉันเอารุ่นที่ไม่ใช่ const ออกมา
darune

1
using value_type = std::remove_cv_t<T>;เป็นสิ่งจำเป็นส่วนใหญ่ถ้าใช้กับการเขียนโปรแกรมแม่แบบ (สำหรับการ VALUE_TYPE ของ 'ช่วง') ที่ หากคุณต้องการใช้ตัววนซ้ำคุณสามารถข้าม / ลบออกได้
darune

6

คุณเกือบจะสามารถใช้std::vectorสิ่งนี้ได้จริงโดยใช้ฟังก์ชันการทำงานของตัวจัดสรรที่กำหนดเองในทางที่ผิดเพื่อส่งกลับตัวชี้ไปยังหน่วยความจำที่คุณต้องการดู ที่จะไม่รับประกันโดยมาตรฐานในการทำงาน (padding, การจัดตำแหน่ง, การเริ่มต้นของค่าที่ส่งกลับมาคุณจะต้องใช้ความเจ็บปวดเมื่อกำหนดขนาดเริ่มต้นและสำหรับผู้ที่ไม่ใช่ดั้งเดิมคุณต้องแฮกคอนสตรัคเตอร์ของคุณ ) แต่ในทางปฏิบัติฉันคาดว่าจะได้รับการปรับแต่งพอ

ไม่เคยทำเช่นนั้น มันน่าเกลียดประหลาดใจแฮ็คและไม่จำเป็น อัลกอริธึมของไลบรารีมาตรฐานได้รับการออกแบบให้ทำงานได้ดีกับอาร์เรย์ดิบเช่นเดียวกับเวกเตอร์ ดูคำตอบอื่น ๆ สำหรับรายละเอียดที่


1
อืมใช่ว่าใช้งานได้กับตัวvectorสร้างที่อ้างอิง Allocator แบบกำหนดเองเป็นตัวสร้าง ARG (ไม่ใช่แค่แม่แบบพารามิเตอร์) ฉันเดาว่าคุณต้องการวัตถุตัวจัดสรรที่มีค่าตัวชี้รันไทม์อยู่ในนั้นไม่ใช่พารามิเตอร์เทมเพลตมิฉะนั้นจะใช้งานได้กับที่อยู่ constexpr เท่านั้น คุณจะต้องระมัดระวังไม่ให้vectorวัตถุเริ่มต้นสร้าง.resize()และเขียนทับข้อมูลที่มีอยู่ ความไม่ตรงกันระหว่างคอนเทนเนอร์ที่เป็นเจ้าของเช่นเวกเตอร์กับช่วงที่ไม่มีการเป็นเจ้าของนั้นใหญ่มากหากคุณเริ่มใช้. push_back ฯลฯ
Peter Cordes

1
@PeterCordes ผมหมายถึงให้ไม่ฝัง Lede - คุณต้องการนอกจากนี้ยังจะต้องมีความบ้า ในใจของฉันสิ่งที่แปลกประหลาดที่สุดเกี่ยวกับความคิดก็คืออินเทอร์เฟซตัวจัดสรรมีconstructวิธีการที่จำเป็น ... ฉันไม่สามารถคิดได้ว่ากรณีการใช้งานที่ไม่แฮ็กต้องใช้อะไรมากกว่าตำแหน่งใหม่
Sneftel

1
กรณีการใช้งานที่ชัดเจนคือการหลีกเลี่ยงการเสียเวลาในการสร้างองค์ประกอบที่คุณกำลังจะเขียนด้วยวิธีอื่นเช่นresize()ก่อนที่คุณจะผ่านการอ้างอิงไปยังสิ่งที่ต้องการใช้เป็นเอาต์พุตบริสุทธิ์ (เช่นการเรียกระบบการอ่าน) ในทางปฏิบัติคอมไพเลอร์มักจะไม่ปรับความทรงจำนั้นให้เหมาะสม หรือถ้าคุณมีตัวจัดสรรที่ใช้ calloc เพื่อรับหน่วยความจำที่มีค่าเป็นศูนย์ล่วงหน้าคุณสามารถหลีกเลี่ยงการทำให้มันสกปรกเหมือนที่คนโง่std::vector<int>ทำตามค่าเริ่มต้นเมื่อสร้างวัตถุเริ่มต้นที่มีรูปแบบบิตเป็นศูนย์ทั้งหมด ดูหมายเหตุใน en.cppreference.com/w/cpp/container/vector/vector
Peter Cordes

4

ดังที่คนอื่น ๆ ชี้ให้เห็นstd::vectorต้องเป็นเจ้าของหน่วยความจำพื้นฐาน (ไม่ยุ่งกับตัวจัดสรรที่กำหนดเอง) ดังนั้นจึงไม่สามารถใช้งานได้

คนอื่นยังแนะนำให้ใช้ช่วง c ++ 20 แต่เห็นได้ชัดว่าต้องใช้ c ++ 20

ฉันจะแนะนำspan-lite span เพื่ออ้างถึงคำบรรยาย:

span lite - การขยายแบบคล้าย C ++ 20 สำหรับ C ++ 98, C ++ 11 และใหม่กว่าในไลบรารีไฟล์ส่วนหัวเดียวเท่านั้น

มันให้มุมมองที่ไม่ได้เป็นเจ้าของและไม่แน่นอน (ในขณะที่คุณสามารถกลายเป็นองค์ประกอบและคำสั่งของพวกเขา แต่ไม่ได้แทรกพวกเขา) และตามที่อ้างว่าไม่มีการอ้างอิงและทำงานบนคอมไพเลอร์ส่วนใหญ่

ตัวอย่างของคุณ:

#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_wrapperงานได้ตั้งแต่ C ++ 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

@eerorika std::copy(std::begin(src_table), std::end(src_table), std::back_inserter(dest_vector));เต็มไปdest_vectorด้วยค่าที่นำมาจากsrc_table(IOW ข้อมูลถูกคัดลอกไปdest_vector) ดังนั้นฉันไม่ได้รับความคิดเห็นของคุณ คุณอธิบายได้ไหม
Jabberwocky

@Jabberwocky ไม่ได้คัดลอกค่า มันเติมเวกเตอร์ ithe พร้อมตัวอ้างอิงอ้างอิง
eerorika

3
@Jabberwocky มันไม่มีประสิทธิภาพมากขึ้นในกรณีที่มีค่าจำนวนเต็ม
eerorika
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.