วิธีที่ง่ายที่สุดในการแปลงอาร์เรย์เป็นเวกเตอร์คืออะไร?


94

วิธีที่ง่ายที่สุดในการแปลงอาร์เรย์เป็นเวกเตอร์คืออะไร?

void test(vector<int> _array)
{
  ...
}

int x[3]={1, 2, 3};
test(x); // Syntax error.

ฉันต้องการแปลง x จากอาร์เรย์ int เป็นเวกเตอร์ด้วยวิธีที่ง่ายที่สุด

คำตอบ:


140

ใช้ตัวvectorสร้างที่ใช้ตัวทำซ้ำสองตัวโปรดทราบว่าพอยน์เตอร์เป็นตัวทำซ้ำที่ถูกต้องและใช้การแปลงโดยปริยายจากอาร์เรย์เป็นพอยน์เตอร์:

int x[3] = {1, 2, 3};
std::vector<int> v(x, x + sizeof x / sizeof x[0]);
test(v);

หรือ

test(std::vector<int>(x, x + sizeof x / sizeof x[0]));

sizeof x / sizeof x[0]เห็นได้ชัดว่าอยู่ที่ไหน3ในบริบทนี้ เป็นวิธีทั่วไปในการรับจำนวนองค์ประกอบในอาร์เรย์ สังเกตว่าx + sizeof x / sizeof x[0]ชี้องค์ประกอบหนึ่งนอกเหนือจากองค์ประกอบสุดท้าย


1
ช่วยอธิบายหน่อยได้ไหม? ฉันอ่านvector<int> a(5,10);ค่าเฉลี่ยmake room for 5 int` แล้วและเริ่มต้นด้วย 10 แต่ x, x + ... ของคุณทำงานอย่างไร? คุณสามารถอธิบาย?
Asif Mushtaq

1
@UnKnown แทนที่จะเลือกvector<int>::vector(size_type, int)มันจะเลือกvector<int>::vector(int*, int*)ซึ่งคัดลอกช่วงที่แสดงโดยพอยน์เตอร์คู่นั้น อย่างแรกคือโอเวอร์โหลด (2) อันที่สองคือโอเวอร์โหลด (4) ที่นี่
Caleth

1
บน c ++ 11 std :: ขอบเขตดีกว่าวิธี sizeof sizeof x / sizeof x[0] == std::extent<decltype(x)>::value
Isaac Pascual

116

โดยส่วนตัวแล้วฉันค่อนข้างชอบแนวทาง C ++ 2011 เพราะไม่ต้องการให้คุณใช้sizeof()หรือจำการปรับขอบเขตอาร์เรย์หากคุณเคยเปลี่ยนขอบเขตอาร์เรย์ (และคุณสามารถกำหนดฟังก์ชันที่เกี่ยวข้องใน C ++ 2003 ได้หากต้องการเช่นกัน ):

#include <iterator>
#include <vector>
int x[] = { 1, 2, 3, 4, 5 };
std::vector<int> v(std::begin(x), std::end(x));

เห็นได้ชัดว่าด้วย C ++ 2011 คุณอาจต้องการใช้รายการ initializer ต่อไป:

std::vector<int> v({ 1, 2, 3, 4, 5 });

2
มันคัดลอกอาร์เรย์หรือแค่ชี้ไปที่มัน? ฉันกังวลกับการแสดง
kirill_igum

2
std::vector<T>เป็นเจ้าของTวัตถุเสมอ สิ่งนี้มีสองนัย: เมื่อแทรกวัตถุลงในเวกเตอร์พวกเขาจะถูกคัดลอกและถูกจัดวางในหน่วยความจำ สำหรับวัตถุที่มีขนาดเล็กพอสมควรเช่นลำดับของสตริงสั้น ๆ การจัดระเบียบเป็นการเพิ่มประสิทธิภาพที่สำคัญ หากวัตถุของคุณมีขนาดใหญ่และมีราคาแพงในการคัดลอกคุณอาจต้องการจัดเก็บ [อย่างใดอย่างหนึ่งทรัพยากรที่มีการจัดการ] ชี้ไปที่วัตถุ แนวทางใดจะมีประสิทธิภาพมากกว่านั้นขึ้นอยู่กับวัตถุ แต่คุณมีทางเลือก
Dietmar Kühl

ดังนั้นหากฉันต้องการเชื่อมต่อกับไลบรารี c ++ และ ac และคัดลอกจาก c-array เป็นเวกเตอร์และย้อนกลับจะไม่มีวิธีใดในการจ่ายค่าปรับ 2 ชุด? (ฉันใช้ eigen library และ gsl)
kirill_igum

16

พอยน์เตอร์สามารถใช้งานได้เหมือนกับตัวทำซ้ำอื่น ๆ :

int x[3] = {1, 2, 3};
std::vector<int> v(x, x + 3);
test(v)

2
ในชีวิตจริงคุณอาจต้องการแยกแยะขนาดอาร์เรย์เช่นใช้const size_t X_SIZE = 3;สำหรับแสดงขนาดอาร์เรย์หรือคำนวณจาก sizeof ฉันละเว้นส่วนนั้นเพื่อประโยชน์ในการอ่าน
Rafał Rawicki

11

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

void test(const std::vector<int>& in) {
  // Iterate over vector and do whatever
}

กลายเป็น:

template <typename Iterator>
void test(Iterator begin, const Iterator end) {
    // Iterate over range and do whatever
}

template <typename Container>
void test(const Container& in) {
    test(std::begin(in), std::end(in));
}

ซึ่งให้คุณทำ:

int x[3]={1, 2, 3};
test(x); // Now correct

( การสาธิตไอดีโอ )


"แทนที่จะบังคับให้ทุกอย่างเป็นเวกเตอร์ให้ถามว่าคุณจะแปลงการทดสอบให้ทำงานกับตัววนซ้ำแทนคอนเทนเนอร์เฉพาะได้อย่างไร" ทำไมถึงดีกว่านี้
aquirdturtle

1
@aquirdturtle เพราะตอนนี้แทนที่จะสนับสนุนเฉพาะเวกเตอร์คุณรองรับรายการและอาร์เรย์และเพิ่มคอนเทนเนอร์และแปลงตัววนซ้ำและช่วงและ ....
Flexo

2
และคุณไม่จำเป็นต้องคัดลอกข้อมูล
Lightness Races in Orbit

2

วิธีง่ายๆวิธีหนึ่งคือการใช้assign()ฟังก์ชันที่กำหนดไว้ล่วงหน้าในvectorคลาส

เช่น

array[5]={1,2,3,4,5};

vector<int> v;
v.assign(array, array+5); // 5 is size of array.

2
เทียบเท่ากับการใช้ ctor ซึ่งกล่าวถึงในคำตอบที่มีอยู่เมื่อเจ็ดปีก่อน ไม่มีอะไรเพิ่ม ...
Lightness Races ในวงโคจร
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.