วิธีแปลงเวกเตอร์เป็นอาเรย์


352

ฉันจะแปลง a std::vector<double>เป็น a ได้double array[]อย่างไร


9
ค่อนข้างจะถามคำถามว่าทำไม? คุณสามารถเข้าถึงเวกเตอร์เป็นอาร์เรย์ อาร์เรย์ทำอะไรที่เวกเตอร์ไม่ได้?
Michael Dorgan

96
@Michael กรณีการใช้งานทั่วไปที่ฉันใช้คือเวกเตอร์ในรหัสของฉันเองและจำเป็นต้องเรียกใช้ฟังก์ชันบุคคลที่สามที่ใช้อาร์เรย์
Michael Mrozek

7
คำศัพท์ที่ถูกโยนไปรอบ ๆ ทำให้เกิดความสับสน ตัวชี้ไม่ใช่อาร์เรย์ เราต้องการให้ตัวชี้ไปยังองค์ประกอบแรกของอาร์เรย์หรืออาร์เรย์หรือไม่?
GManNickG

7
เป็นคำถามจริงอย่างแน่นอน - ค่อนข้างง่ายตีความได้ง่ายเช่นกัน โปรดเปิดใหม่อีกครั้ง
dbliss

10
"Kinda ถามคำถามว่าทำไม?" - ขั้นแรกให้ใช้วลีนั้นในทางที่ผิด ประการที่สองมันมีเลือดออกชัดเจนว่าทำไม
Jim Balter

คำตอบ:


534

มีเคล็ดลับที่ค่อนข้างง่ายในการทำเช่นนี้เนื่องจาก spec ในขณะนี้รับประกันเวกเตอร์จัดเก็บองค์ประกอบของพวกเขาอย่างต่อเนื่อง:

std::vector<double> v;
double* a = &v[0];

29
@ganuke คุณไม่ได้คัดลอกคุณกำลังสร้างตัวชี้ที่ชี้ไปยังอาร์เรย์จริงที่เวกเตอร์ใช้อยู่ภายใน หากคุณต้องการคัดลอกคำตอบของ GManจะอธิบายได้อย่างไร
Michael Mrozek

4
@ganuke: "อาร์เรย์" คืออะไร? คุณจำเป็นต้องให้ข้อมูลเพิ่มเติม. ภาพใหญ่คืออะไร
GManNickG

6
@ganuke คุณไม่จำเป็นต้องมีdouble*จุดที่ชี้ไปยังข้อมูลเดียวกัน คำตอบนี้ใช้ได้กับกรณีนั้น
Michael Mrozek

6
@guneykayim เวกเตอร์เป็นเจ้าของหน่วยความจำนั้นคุณไม่ควรปล่อยให้เป็นอิสระ
Michael Mrozek

23
std::vector<double> v; double* a = v.data();
sinoTrinity

148

เพื่ออะไร? คุณต้องชี้แจง: คุณต้องการตัวชี้ไปยังองค์ประกอบแรกของอาร์เรย์หรืออาร์เรย์หรือไม่?

หากคุณกำลังเรียกฟังก์ชัน API ที่คาดว่าอดีตคุณสามารถทำอะไรdo_something(&v[0], v.size())ที่vเป็นเวกเตอร์ของdoubles องค์ประกอบของเวกเตอร์นั้นต่อเนื่องกัน

มิฉะนั้นคุณต้องคัดลอกแต่ละองค์ประกอบ:

double arr[100];
std::copy(v.begin(), v.end(), arr);

ตรวจสอบให้แน่ใจว่าไม่เพียง แต่arrมีขนาดใหญ่พอ แต่ที่arrจะเติมให้เต็มหรือคุณมีค่าเริ่มต้น


15
หมายเหตุ: ใช้ v.size () เพื่อรับจำนวนองค์ประกอบสำหรับอาร์เรย์ใหม่: double arr [v.size ()];
rbaleksandar

7
@rbaleksandar: อาร์เรย์ไม่สามารถมีขนาดนิพจน์ที่ไม่คงที่ได้
GManNickG

@GManNickG: มันใช้งานได้ แต่ฉันคิดว่ามันมีความเข้าใจผิดอยู่บ้าง ลองนึกภาพสิ่งต่อไปนี้: คุณมีคลาสที่มีพอยน์เตอร์หลายประเภทที่ต้องชี้ไปที่อาร์เรย์ซึ่งไม่ทราบว่าคุณกำหนดชั้นเรียนของคุณเมื่อใดและสร้างในภายหลังโดยล้างเวกเตอร์ต่างๆและใช้ขนาดพารามิเตอร์ เพื่อกำหนดจำนวนพื้นที่ที่จะใช้ อีกตัวอย่าง: ฟังก์ชั่นง่าย ๆ เป็นโมฆะ arrayTest (int arrSize ไม่ได้ลงนาม) ที่สร้างอาร์เรย์ (สั้น ๆ [arrSize];) ในนั้นโดยใช้ฟังก์ชั่นพารามิเตอร์สำหรับขนาด
rbaleksandar

1
@rbaleksandar ไม่มีความเข้าใจผิด; ใน C ++ 11 และก่อนหน้าขนาดอาร์เรย์ต้องเป็นนิพจน์ค่าคงที่แบบรวม ตัวอย่างฟังก์ชั่นของคุณคือการใช้งานทั่วไปสำหรับ VLA ใน C แต่รองรับเฉพาะส่วนขยาย (ที่ไม่เป็นมาตรฐาน) ใน C ++ มันอาจจะมากับ C ++ 14 แม้ว่า: stackoverflow.com/a/17318040/87234 แต่ ณ ตอนนี้มันไม่ใช่ตัวเลือกมาตรฐาน
GManNickG

1
@GManNickG ฉันคิดว่า @Jet กำลังบอกว่าถ้าคุณต้องการแปลงเวกเตอร์เป็นอาร์เรย์และคุณต้องการกำหนดขนาดอาร์เรย์โดยใช้size()ฟังก์ชันของstd:vectorคุณจะต้องใช้newหรือmallocทำเช่นนั้น ตามที่ได้อธิบายไว้แล้ว (โดยคุณ) ว่าdouble arr[v.size()]ไม่ถูกต้อง การใช้เวกเตอร์แทนสิ่งใหม่เป็นความคิดที่ดี แต่ประเด็นทั้งหมดของคำถามคือวิธีที่คุณสามารถแปลงเวกเตอร์เป็นอาร์เรย์
RyanP


17
vector<double> thevector;
//...
double *thearray = &thevector[0];

สิ่งนี้รับประกันว่าจะทำงานได้ตามมาตรฐานอย่างไรก็ตามมีข้อแม้บางประการ: โดยเฉพาะอย่างยิ่งให้ใช้เฉพาะthearrayเมื่อthevectorอยู่ในขอบเขตเท่านั้น


4
... และตรวจสอบให้แน่ใจว่าเวกเตอร์ไม่ได้เป็นempty()อย่างอื่นสิ่งนี้จะก่อให้เกิด UB ที่น่ากลัว
sbi

13

เวกเตอร์อย่างมีประสิทธิภาพคืออาร์เรย์ใต้ผิวหนัง หากคุณมีฟังก์ชั่น:

void f( double a[]);

คุณสามารถเรียกมันว่าแบบนี้:

vector <double> v;
v.push_back( 1.23 )
f( &v[0] );

คุณไม่จำเป็นต้องแปลงเวกเตอร์เป็นอินสแตนซ์อาร์เรย์จริง


1
ฉันคิดว่าคุณหมายถึงf( &v[0] );บรรทัดสุดท้ายของคุณ
Michael Mrozek

10

ตามที่ std::vector<int> vec vec ที่จะได้รับint*คุณสามารถใช้สองวิธี:

  1. int * arr = & vec [0];

  2. int * arr = vec.data ();

หากคุณต้องการแปลงTเวคเตอร์ประเภทใด ๆให้T* arrayเปลี่ยนข้างบนintTไป

ฉันจะแสดงให้คุณเห็นว่าทำไมผลงานทั้งสองข้างต้นเพื่อความเข้าใจที่ดี

std::vector เป็นอาร์เรย์แบบไดนามิกเป็นหลัก

สมาชิกข้อมูลหลักดังนี้:

template <class T, class Alloc = allocator<T>>
class vector{
    public:
        typedef T          value_type;
        typedef T*         iterator;
        typedef T*         pointer;
        //.......
    private:
        pointer start_;
        pointer finish_;
        pointer end_of_storage_;

    public:
        vector():start_(0), finish_(0), end_of_storage_(0){}
    //......
}

range (start_, end_of_storage_)เป็นหน่วยความจำทั้งหมดอาร์เรย์เวกเตอร์จัดสรร;

range(start_, finish_)เป็นหน่วยความจำทั้งหมดอาร์เรย์เวกเตอร์ที่ใช้;

range(finish_, end_of_storage_)คือหน่วยความจำอาร์เรย์สำรอง

ตัวอย่างเช่นเป็น vec เวกเตอร์ ซึ่งมี {9, 9, 1, 2, 3, 4} ตัวชี้อาจต้องการด้านล่าง

ป้อนคำอธิบายรูปภาพที่นี่

ดังนั้น&vec[0]= start_ (address.) (start_ เทียบเท่ากับ int * array head)

ในฟังก์ชันสมาชิกเพียงแค่กลับ start_c++11data()

pointer data()
{ 
     return start_; //(equivalent to `value_type*`, array head)
}

2

เราสามารถทำได้โดยใช้วิธี data () C ++ 11 ให้วิธีการนี้

ตัวอย่างโค้ด

#include<bits/stdc++.h>
using namespace std;


int main()
{
  ios::sync_with_stdio(false);

  vector<int>v = {7, 8, 9, 10, 11};
  int *arr = v.data();

  for(int i=0; i<v.size(); i++)
  {
    cout<<arr[i]<<" ";
  }

  return 0;
}


1

foo(&array[0], array.size());ถ้าคุณมีฟังก์ชั่นแล้วคุณอาจจะต้องนี้: หากคุณจัดการกับสถานการณ์ที่คุณต้องการอาเรย์แล้วคุณจะต้องปรับโครงสร้างเวกเตอร์นั้นเป็นอาร์เรย์แบบขยายโดยทั่วไปคุณควรใช้มัน


-1

คุณสามารถทำอะไรเช่นนี้

vector <int> id;
vector <double> v;

if(id.size() > 0)
{
    for(int i = 0; i < id.size(); i++)
    {
        for(int j = 0; j < id.size(); j++)
        {
            double x = v[i][j];
            cout << x << endl;
        }
    }
}

v [i] [j]; สำหรับอาร์เรย์ 2 มิติ
Sakthi Vignesh
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.