วิธีที่ง่ายที่สุดในการเริ่มต้น std :: vector ด้วยองค์ประกอบ hardcoded คืออะไร?


611

ฉันสามารถสร้างอาร์เรย์และเริ่มต้นได้เช่นนี้

int a[] = {10, 20, 30};

ฉันจะสร้างstd::vectorและเริ่มต้นมันอย่างสง่างามในทำนองเดียวกันได้อย่างไร

วิธีที่ดีที่สุดที่ฉันรู้คือ:

std::vector<int> ints;

ints.push_back(10);
ints.push_back(20);
ints.push_back(30);

มีวิธีที่ดีกว่า?


1
ถ้าคุณจะไม่เปลี่ยนขนาดของ ints หลังจากเริ่มต้นพิจารณาการใช้อาร์เรย์ tr1
zr

@zr คุณมีฉันอยากรู้อยากเห็น ... ถ้าฉันต้องการขนาดคงที่ฉันไม่สามารถใช้อาร์เรย์แบบเก่าธรรมดาได้หรือไม่? ดูอาร์เรย์ tr1 ในขณะนี้ ...
Agnel Kurian

2
tr1::arrayมีประโยชน์เนื่องจากอาร์เรย์ทั่วไปไม่มีส่วนต่อประสานของคอนเทนเนอร์ STL
Manuel

เปลี่ยนชื่อเพื่อให้เป็นคำถาม C ++ 03 อย่างชัดเจน ดูเหมือนง่ายกว่าที่จะผ่านและแก้ไขคำตอบทั้งหมดเพื่อให้เข้าใจกับมาตรฐาน C ++ ใหม่
TED

นี้เรียกว่าการเริ่มต้นรายการ
Alan Dawkins

คำตอบ:


548

วิธีหนึ่งคือการใช้อาร์เรย์เพื่อเริ่มต้นเวกเตอร์

static const int arr[] = {16,2,77,29};
vector<int> vec (arr, arr + sizeof(arr) / sizeof(arr[0]) );

7
@Agnel มันจะทำงานได้ดีโดยไม่ต้องมีstaticหรือconstอย่างไรก็ตามพวกเขาทั้งสองทำให้ชัดเจนยิ่งขึ้นว่าควรใช้อย่างไรและอนุญาตให้คอมไพเลอร์ทำการปรับให้เหมาะสมเพิ่มเติม
Yacoby

68
ฉันไม่ได้ลดขนาดเรื่องนี้ลง แต่ฉันถูกล่อลวง ส่วนใหญ่เป็นเพราะสิ่งนี้ช่วยให้คุณประหยัดแทบไม่มีอะไรเลยเพียงแค่ใช้อาเรย์เริ่มต้นในตอนแรก อย่างไรก็ตามนั่นเป็นความผิดของ C ++ ไม่ใช่ของคุณ
TED

2
คุณช่วยอธิบายได้ไหมว่าทำไมคุณถึงใช้พารามิเตอร์เหล่านั้นเมื่อกำหนดเวกเตอร์ vec
DomX23

13
sizeof (array) เป็นหนึ่งในข้อยกเว้นบางประการที่อนุญาตให้รับขนาดทั้งหมดขององค์ประกอบของอาร์เรย์และไม่ใช่มิติตัวชี้ arr ดังนั้นโดยทั่วไปเขาใช้ vector (pointer_to_first_element, pointer_to_first_element + size_in_bytes_of_the_whole_array / size_of_one_element) นั่นคือ: vector (pointer_to_first_element, pointer_after_final_element) ประเภทได้รับมาพร้อมกับ <int> ดังนั้นเวกเตอร์จึงรู้ว่าองค์ประกอบหนึ่งรายการมีเท่าใด โปรดจำไว้ว่าตัววนซ้ำสามารถใช้เป็นตัวชี้เพื่อให้คุณใช้เวกเตอร์ (ตัวเริ่มต้นตัววนปลายตัววนซ้ำ) ตัวสร้าง
Johnny Pauling

11
@TED: บางครั้งคุณต้องแก้ไขเวกเตอร์ที่ได้ ตัวอย่างเช่นคุณอาจต้องมีพารามิเตอร์เริ่มต้นเสมอและบางครั้งก็เพิ่มพารามิเตอร์ที่กำหนดเอง
DarkWanderer

641

หากคอมไพเลอร์ของคุณรองรับ C ++ 11 คุณสามารถทำได้ดังนี้:

std::vector<int> v = {1, 2, 3, 4};

นี้สามารถใช้ได้ใน GCC เป็นรุ่น 4.4 น่าเสียดายที่ VC ++ 2010 ดูเหมือนจะล้าหลังในแง่นี้

อีกทางหนึ่งคือห้องสมุดBoost.Assignใช้เวทย์มนตร์ที่ไม่ใช่มาโครเพื่ออนุญาตดังต่อไปนี้:

#include <boost/assign/list_of.hpp>
...
std::vector<int> v = boost::assign::list_of(1)(2)(3)(4);

หรือ:

#include <boost/assign/std/vector.hpp>
using namespace boost::assign;
...
std::vector<int> v;
v += 1, 2, 3, 4;

แต่โปรดจำไว้ว่าสิ่งนี้มีค่าใช้จ่ายบางส่วน (โดยทั่วไปlist_ofสร้างstd::dequeภายใต้ประทุน) ดังนั้นสำหรับโค้ดที่มีประสิทธิภาพที่สำคัญคุณควรที่จะทำอย่างที่ Yacoby กล่าว


เนื่องจากเวกเตอร์มีขนาดตัวเองมันจะโอเคที่จะเริ่มต้นมันว่างเปล่าด้วยหรือไม่ ชอบในการสร้าง: this->vect = {};?
Azurespot

3
@ Azurespot คุณสามารถเริ่มต้นได้และมันจะว่างเปล่า:std::vector<T> vector;
ลุค

2
ในกรณีที่ใครบางคนอาจจะอยากรู้เกี่ยวกับstd::vector<int> v = {1, 2, 3, 4};เวกเตอร์ของinitializer list constructorจะได้รับการเรียกร้องให้มีการเรียงลำดับของการเริ่มต้นนี้เอกสารที่สามารถพบได้ในส่วนC++ 11
simomo

103

หากทำได้ให้ใช้วิธี C ++ ที่ทันสมัย ​​[11,14,17, ... ]

std::vector<int> vec = {10,20,30};

วิธีเก่า ๆ ของการวนลูปมากกว่าอาเรย์ที่มีความยาวผันแปรหรือการใช้sizeof()นั้นน่ากลัวอย่างแท้จริงในสายตาและไม่จำเป็นอย่างยิ่งในแง่ของค่าใช้จ่ายทางจิต yuck


2
ในความเป็นจริงนี้เป็นคำถาม C ++ 03 แต่ฉันหวังว่าผู้คน / บริษัท จะนำมาตรฐานใหม่มาใช้ C ++ ยังต้องการการปรับใช้อาเรย์แบบความยาวผันแปร (VLA) ในไลบรารีมาตรฐานคล้ายกับที่มีใน Eigen และ Boost
Adam Erickson

แต่น่าเสียดายที่วิธีการนี้เป็นปัญหาในบางกรณีเช่นopen-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1467 yuck
Lightness Races ที่ Orbit

หาก "รายการเริ่มต้นของการรวมจากวัตถุประเภทเดียวกัน" เป็นสิ่งที่คุณอาจมีปัญหาที่ใหญ่กว่าใน codebase ของคุณ ... ฉันคิดว่าไม่มีแอปพลิเคชันที่จะแก้ปัญหาการแก้จุดบกพร่อง
Adam Erickson

77

ใน C ++ 0x คุณจะสามารถทำได้ในลักษณะเดียวกับที่คุณทำกับอาร์เรย์ แต่ไม่อยู่ในมาตรฐานปัจจุบัน

ด้วยการสนับสนุนด้านภาษาเท่านั้นคุณสามารถใช้:

int tmp[] = { 10, 20, 30 };
std::vector<int> v( tmp, tmp+3 ); // use some utility to avoid hardcoding the size here

หากคุณสามารถเพิ่มห้องสมุดอื่น ๆ คุณสามารถลองเพิ่ม :: assignment:

vector<int> v = list_of(10)(20)(30);

ในการหลีกเลี่ยงการเข้ารหัสขนาดของอาเรย์

// option 1, typesafe, not a compile time constant
template <typename T, std::size_t N>
inline std::size_t size_of_array( T (&)[N] ) {
   return N;
}
// option 2, not typesafe, compile time constant
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))

// option 3, typesafe, compile time constant
template <typename T, std::size_t N>
char (&sizeof_array( T(&)[N] ))[N];    // declared, undefined
#define ARRAY_SIZE(x) sizeof(sizeof_array(x))

แน่นอนว่าฉันไม่ได้ลงคะแนน แต่ฉันมีคำถามอยู่แล้ว: เมื่อใดขนาดของอาเรย์ที่ไม่คงที่รวมเวลา? คือในกรณีใดคุณจะใช้วิธีแก้ปัญหาแรกในตัวอย่างที่สองของคุณเมื่อเทียบกับวิธีที่สาม?
มานูเอล

4
@Manuel ขนาดของอาร์เรย์เป็นส่วนหนึ่งของประเภทและเป็นเช่นนี้เป็นค่าคงที่เวลารวบรวม ตอนนี้ตัวเลือก 1 ใช้ค่าคงที่เวลาคอมไพล์ที่ 'N' เป็นค่าส่งคืนสำหรับฟังก์ชัน การส่งคืนของฟังก์ชันไม่ใช่เวลาคอมไพล์ แต่เป็นค่ารันไทม์แม้ว่ามันอาจจะได้รับการ inline เป็นค่าคงที่ของการโทร ความแตกต่างคือการที่คุณไม่สามารถทำ: ในขณะที่คุณสามารถทำได้int another[size_of_array(array)] int another[ARRAY_SIZE(array)]
David Rodríguez - dribeas

1
ในตัวเลือกที่ 3: ฉันไม่ได้สิ่งที่คุณหมายถึงด้วย "ประกาศ, ไม่ได้กำหนด"? ดังนั้นตัวแปรจะไม่ใช้หน่วยความจำเพิ่มเติมหรือไม่
To1ne

1
@ To1ne ที่จริง ๆ แล้วเป็นการประกาศฟังก์ชันไม่ใช่ตัวแปร เหตุผลหรือการกำหนดคือเราไม่ต้องการฟังก์ชั่นสำหรับสิ่งอื่นใดนอกจากการsizeofแสดงออกที่ไม่ต้องการคำจำกัดความ ในขณะที่คุณสามารถให้คำจำกัดความได้จริงการทำอย่างถูกต้องจะต้องมีการจัดสรรแบบคงที่ของอาร์เรย์และส่งกลับการอ้างอิงไปยังมันและคำถามถัดไปจะเป็นสิ่งที่เหมาะสมสำหรับค่าอาร์เรย์? (โปรดทราบว่านี่หมายถึงหนึ่งอาเรย์ต่อการผสมประเภท / ขนาดของอินสแตนซ์ของฟังก์ชั่น!) เนื่องจากไม่มีเหตุผลที่เหมาะสมสำหรับมันฉันจึงควรหลีกเลี่ยง
David Rodríguez - dribeas

1
@mhd: คุณไม่สามารถสร้างอาร์เรย์ว่างในภาษา 'int arr [0] = {};' ไม่ใช่รหัส C ++ ที่ถูกต้อง แต่คุณถูกต้องว่าถ้าคุณต้องการเริ่มต้นเวกเตอร์เปล่าและเวกเตอร์ที่ไม่ว่างคุณจะต้องใช้โครงสร้างที่แตกต่างกัน ตั้งแต่ C ++ 11 นี่ไม่ใช่ปัญหาเนื่องจากคุณสามารถใช้ตัวสร้างรายการเริ่มต้น
David Rodríguez - dribeas

61

ใน C ++ 11:

#include <vector>
using std::vector;
...
vector<int> vec1 { 10, 20, 30 };
// or
vector<int> vec2 = { 10, 20, 30 };

ใช้ boost list_of:

#include <vector>
#include <boost/assign/list_of.hpp>
using std::vector;
...
vector<int> vec = boost::assign::list_of(10)(20)(30);

ใช้เพิ่มมอบหมาย:

#include <vector>
#include <boost/assign/std/vector.hpp>
using std::vector;
...
vector<int> vec;
vec += 10, 20, 30;

ธรรมดา STL:

#include <vector>
using std::vector;
...
static const int arr[] = {10,20,30};
vector<int> vec (arr, arr + sizeof(arr) / sizeof(arr[0]) );

STL ทั่วไปที่มีมาโครทั่วไป:

#include <vector>
#define ARRAY_SIZE(ar) (sizeof(ar) / sizeof(ar[0])
#define ARRAY_END(ar) (ar + ARRAY_SIZE(ar))
using std::vector;
...
static const int arr[] = {10,20,30};
vector<int> vec (arr, ARRAY_END(arr));

Conventional STL ที่มีแมโคร initializer แบบเวกเตอร์:

#include <vector>
#define INIT_FROM_ARRAY(ar) (ar, ar + sizeof(ar) / sizeof(ar[0])
using std::vector;
...
static const int arr[] = {10,20,30};
vector<int> vec INIT_FROM_ARRAY(arr);

2
C ++ 11 รองรับstd::beginและstd::endสำหรับอาเรย์ด้วยดังนั้นเวกเตอร์ก็สามารถเริ่มต้นได้เช่นstatic const int arr[] = {10,20,30}; vector<int> vec(begin(arr), end(arr));กัน
Jaege

54

แค่คิดว่าฉันจะโยนใน $ 0.02 ของฉัน ฉันมักจะประกาศสิ่งนี้:

template< typename T, size_t N >
std::vector<T> makeVector( const T (&data)[N] )
{
    return std::vector<T>(data, data+N);
}

ในส่วนหัวยูทิลิตี้ที่ไหนสักแห่งแล้วสิ่งที่จำเป็นคือ:

const double values[] = { 2.0, 1.0, 42.0, -7 };
std::vector<double> array = makeVector(values);

แต่ฉันไม่สามารถรอ C ++ 0x ฉันติดขัดเพราะรหัสของฉันจะต้องรวบรวมใน Visual Studio หุยฮา


1
เทคนิคนี้สามารถใช้เพื่อโอเวอร์โหลดฟังก์ชันเพื่อยอมรับอาร์เรย์ที่มีขนาดที่พิมพ์
Andres Riofrio

4
คุณอธิบายconst T (&data)[N]ส่วนนี้ได้ไหม ขนาดของอาเรย์จะลดขนาดในการโทรของคุณเป็นmakeVector(values)อย่างไร?
Patryk

36

ก่อน C ++ 11:

วิธีที่ 1 =>

vector<int> v(arr, arr + sizeof(arr)/sizeof(arr[0]));
vector<int>v;

วิธีที่ 2 =>

 v.push_back(SomeValue);

C ++ 11 เป็นต้นไปด้านล่างยังเป็นไปได้

vector<int>v = {1, 3, 5, 7};

28

เริ่มต้นด้วย:

int a[] = {10, 20, 30}; //i'm assuming a is just a placeholder

หากคุณไม่มีคอมไพเลอร์ C ++ 11 และคุณไม่ต้องการใช้การเพิ่ม:

const int a[] = {10, 20, 30};
const std::vector<int> ints(a,a+sizeof(a)/sizeof(int)); //make it const if you can

หากคุณไม่มีคอมไพเลอร์ C ++ 11 และสามารถใช้การเพิ่ม:

#include <boost/assign.hpp>
const std::vector<int> ints = boost::assign::list_of(10)(20)(30);

หากคุณมีคอมไพเลอร์ C ++ 11:

const std::vector<int> ints = {10,20,30};

22

สำหรับการเริ่มต้นเวกเตอร์ -

vector<int> v = {10,20,30}

สามารถทำได้ถ้าคุณมีคอมไพเลอร์ c ++ 11

มิฉะนั้นคุณสามารถมีอาร์เรย์ของข้อมูลแล้วใช้สำหรับวง

int array[] = {10,20,30}
for(unsigned int i=0; i<sizeof(array)/sizeof(array[0]); i++)
{
     v.push_back(array[i]);
}

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



16

va_argฉันสร้างโซลูชันของตัวเองโดยใช้ โซลูชันนี้เป็นไปตามมาตรฐาน C ++ 98

#include <cstdarg>
#include <iostream>
#include <vector>

template <typename T>
std::vector<T> initVector (int len, ...)
{
  std::vector<T> v;
  va_list vl;
  va_start(vl, len);
  for (int i = 0; i < len; ++i)
    v.push_back(va_arg(vl, T));
  va_end(vl);
  return v;
}

int main ()
{
  std::vector<int> v = initVector<int> (7,702,422,631,834,892,104,772);
  for (std::vector<int>::const_iterator it = v.begin() ; it != v.end(); ++it)
    std::cout << *it << std::endl;
  return 0;
}

การสาธิต


14

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

#define INIT_VECTOR(type, name, ...) \
static const type name##_a[] = __VA_ARGS__; \
vector<type> name(name##_a, name##_a + sizeof(name##_a) / sizeof(*name##_a))

ด้วยแมโครนี้คุณสามารถกำหนดเวกเตอร์ที่เริ่มต้นด้วยรหัสดังนี้:

INIT_VECTOR(int, my_vector, {1, 2, 3, 4});

นี่จะสร้างเวกเตอร์ใหม่ของ ints ชื่อ my_vector พร้อมองค์ประกอบ 1, 2, 3, 4


13

หากคุณไม่ต้องการใช้การเพิ่ม แต่ต้องการเพลิดเพลินกับไวยากรณ์เช่น

std::vector<int> v;
v+=1,2,3,4,5;

เพียงรวมรหัสอันนี้

template <class T> class vector_inserter{
public:
    std::vector<T>& v;
    vector_inserter(std::vector<T>& v):v(v){}
    vector_inserter& operator,(const T& val){v.push_back(val);return *this;}
};
template <class T> vector_inserter<T> operator+=(std::vector<T>& v,const T& x){
    return vector_inserter<T>(v),x;
}

1
ฉันไม่สามารถหาวิธีใช้รหัสนี้ได้ แต่มันก็ดูน่าสนใจ
Daniel Buckmaster

มันเหมือนหนึ่งในความคิดเห็นข้างต้นกล่าวว่า เพียงแค่บรรทุกเกิน + + และเครื่องหมายจุลภาค ใส่วงเล็บเพื่อความชัดเจน: ((((v+=1),2),3),4),5) นี่คือวิธีการทำงาน: ครั้งแรกที่vector<T> += Tส่งกลับค่าความ vector_inserter ช่วยให้เรียกว่าviที่แค็ปซูลเวกเตอร์เดิมแล้วvi,Tเพิ่ม T เพื่อเวกเตอร์เดิมซึ่งviแค็ปซูลและส่งกลับมาด้วยตัวเองเพื่อให้เราสามารถทำvi,Tอีกครั้ง
ปิติอ่องมงคลกุล

รหัสนี้ทำงานไม่ถูกต้องใน gcc 4.2.1 ฉันคิดว่าเนื่องจากการอ้างอิงกลับไปที่ตัวแปรท้องถิ่นในตัวดำเนินการ + = แต่แนวคิดนั้นยอดเยี่ยม ฉันแก้ไขโค้ดและมีตัวสร้างสำเนาอีกหนึ่งรายการปรากฏขึ้น flow is now -> + = -> ctor -> comma -> copy -> dtor -> จุลภาค ...... -> comma -> dtor
Yevhen

ฉันอาจจะโหลดมากเกินไป << แทนที่จะเป็น + = อย่างน้อย << มีกฎผลข้างเคียงที่คลุมเครืออยู่แล้วเนื่องจากการเลื่อนบิตและชุดออก
Speed8ump

11

ใน C ++ 11:

static const int a[] = {10, 20, 30};
vector<int> vec (begin(a), end(a));

21
หากคุณกำลังใช้ C ++ 11 แล้วคุณเช่นกันอาจจะไปสำหรับวิธีโดยตรง vector<int> arr = {10, 20, 30};-
Bernhard Barker

ที่จริงฉันมี int ขาเข้า [] (บาง C lib) และต้องการที่จะผลักดันให้เป็นเวกเตอร์ (C ++ lib) คำตอบนี้ช่วยได้ส่วนที่เหลือไม่ได้ ;-)
เนบิวลา

10

คุณสามารถทำได้โดยใช้ boost :: assign

vector<int> values;  
values += 1,2,3,4,5,6,7,8,9;

รายละเอียดที่นี่


19
ฉันไม่ได้เห็นกรณีที่แย่กว่านั้นของผู้ให้บริการมากเกินไปการละเมิดในระยะเวลานาน ไม่+=มีตะปูบน 1,2,3,4 .. ถึงจุดสิ้นสุดของค่าหรือไม่ได้เพิ่ม 1 ถึงองค์ประกอบที่ 1, 2 ถึงองค์ประกอบที่ 2, 3 ถึงองค์ประกอบที่ 3 (ตามไวยากรณ์เช่นนี้ควรใน MATLAB- เหมือนภาษา)
bobobobo

10

คำถามที่ซ้ำกันเมื่อเร็ว ๆ นี้มีคำตอบนี้โดยวิคเตอร์ Sehr สำหรับฉันมันมีขนาดกะทัดรัดน่าดึงดูดสายตา (ดูเหมือนว่าคุณกำลัง 'ผลัก' ค่าใน) ไม่ต้องการ c ++ 11 หรือโมดูลบุคคลที่สามและหลีกเลี่ยงการใช้ตัวแปรพิเศษ (เขียน) ด้านล่างเป็นวิธีที่ฉันใช้กับการเปลี่ยนแปลงเล็กน้อย ฉันอาจเปลี่ยนเป็นการขยายการทำงานของเวกเตอร์และ / หรือ va_arg ในอนาคตได้


// Based on answer by "Viktor Sehr" on Stack Overflow
// https://stackoverflow.com/a/8907356
//
template <typename T>
class mkvec {
public:
    typedef mkvec<T> my_type;
    my_type& operator<< (const T& val) {
        data_.push_back(val);
        return *this;
    }
    my_type& operator<< (const std::vector<T>& inVector) {
        this->data_.reserve(this->data_.size() + inVector.size());
        this->data_.insert(this->data_.end(), inVector.begin(), inVector.end());
        return *this;
    }
    operator std::vector<T>() const {
        return data_;
    }
private:
    std::vector<T> data_;
};

std::vector<int32_t>    vec1;
std::vector<int32_t>    vec2;

vec1 = mkvec<int32_t>() << 5 << 8 << 19 << 79;  
// vec1 = (5,8,19,79)
vec2 = mkvec<int32_t>() << 1 << 2 << 3 << vec1 << 10 << 11 << 12;  
// vec2 = (1,2,3,5,8,19,79,10,11,12)

7

วิธีการด้านล่างสามารถใช้ในการเริ่มต้นเวกเตอร์ใน c ++

  1. int arr[] = {1, 3, 5, 6}; vector<int> v(arr, arr + sizeof(arr)/sizeof(arr[0]));

  2. vector<int>v; v.push_back(1); v.push_back(2); v.push_back(3); และอื่น ๆ

  3. vector<int>v = {1, 3, 5, 7};

อันที่สามได้รับอนุญาตเฉพาะใน C ++ 11 เป็นต้นไป


5

มีคำตอบที่ดีมากมายที่นี่ แต่เนื่องจากฉันมาถึงของตัวเองก่อนที่จะอ่านสิ่งนี้ฉันคิดว่าฉันจะขว้างระเบิดที่นี่ต่อไป ...

นี่เป็นวิธีการที่ฉันใช้สำหรับสิ่งนี้ซึ่งจะใช้ได้กับคอมไพเลอร์และแพลตฟอร์ม:

สร้าง struct หรือคลาสเป็นคอนเทนเนอร์สำหรับคอลเลกชันของวัตถุ กำหนดฟังก์ชั่นการทำงานเกินพิกัดสำหรับ <<

class MyObject;

struct MyObjectList
{
    std::list<MyObject> objects;
    MyObjectList& operator<<( const MyObject o )
    { 
        objects.push_back( o );
        return *this; 
    }
};

คุณสามารถสร้างฟังก์ชั่นที่ใช้โครงสร้างของคุณเป็นพารามิเตอร์เช่น:

someFunc( MyObjectList &objects );

จากนั้นคุณสามารถเรียกใช้ฟังก์ชันดังกล่าวได้ดังนี้

someFunc( MyObjectList() << MyObject(1) <<  MyObject(2) <<  MyObject(3) );

ด้วยวิธีนี้คุณสามารถสร้างและส่งต่อคอลเลกชันวัตถุที่มีขนาดแบบไดนามิกไปยังฟังก์ชั่นในหนึ่งบรรทัดใหม่!


4

หากคุณต้องการบางสิ่งในการสั่งซื้อทั่วไปเช่นเดียวกับ Boost :: assign โดยไม่ต้องสร้างการขึ้นต่อกับ Boost สิ่งต่อไปนี้จะคล้ายกันอย่างน้อย:

template<class T>
class make_vector {
    std::vector<T> data;
public:
    make_vector(T const &val) { 
        data.push_back(val);
    }

    make_vector<T> &operator,(T const &t) {
        data.push_back(t);
        return *this;
    }

    operator std::vector<T>() { return data; }
};

template<class T> 
make_vector<T> makeVect(T const &t) { 
    return make_vector<T>(t);
}

ในขณะที่ฉันต้องการไวยากรณ์สำหรับการใช้มันสะอาด แต่ก็ยังไม่น่ากลัวโดยเฉพาะ:

std::vector<int> x = (makeVect(1), 2, 3, 4);

4
typedef std::vector<int> arr;

arr a {10, 20, 30};       // This would be how you initialize while defining

เพื่อรวบรวมการใช้งาน:

clang++ -std=c++11 -stdlib=libc++  <filename.cpp>

คำถามระบุ C ++ 03 (ไม่ใช่ 11)
Mike P

1
ฉันคิดว่ามันไม่ได้ระบุ 03 เมื่อฉันตอบคำถามนี้ จำไม่ได้ว่าสมบูรณ์แบบ อย่างไรก็ตามมันยังคงเป็นคำตอบที่มีประโยชน์สำหรับคนที่กำลังมองหาวิธีแก้ปัญหาอย่างรวดเร็ว
shaveenk

4
// Before C++11
// I used following methods:

// 1.
int A[] = {10, 20, 30};                              // original array A

unsigned sizeOfA = sizeof(A)/sizeof(A[0]);           // calculate the number of elements

                                                     // declare vector vArrayA,
std::vector<int> vArrayA(sizeOfA);                   // make room for all
                                                     // array A integers
                                                     // and initialize them to 0 

for(unsigned i=0; i<sizeOfA; i++)
    vArrayA[i] = A[i];                               // initialize vector vArrayA


//2.
int B[] = {40, 50, 60, 70};                          // original array B

std::vector<int> vArrayB;                            // declare vector vArrayB
for (unsigned i=0; i<sizeof(B)/sizeof(B[0]); i++)
    vArrayB.push_back(B[i]);                         // initialize vArrayB

//3.
int C[] = {1, 2, 3, 4};                              // original array C

std::vector<int> vArrayC;                            // create an empty vector vArrayC
vArrayC.resize(sizeof(C)/sizeof(C[0]));              // enlarging the number of 
                                                     // contained elements
for (unsigned i=0; i<sizeof(C)/sizeof(C[0]); i++)
     vArrayC.at(i) = C[i];                           // initialize vArrayC


// A Note:
// Above methods will work well for complex arrays
// with structures as its elements.

4

หากอาร์เรย์คือ:

int arr[] = {1, 2, 3};
int len = (sizeof(arr)/sizeof(arr[0])); // finding length of array
vector < int > v;
std:: v.assign(arr, arr+len); // assigning elements from array to vector 

4

การสร้างเวกเตอร์อินไลน์ค่อนข้างสะดวกโดยไม่ต้องกำหนดตัวแปรเมื่อเขียนการทดสอบตัวอย่างเช่น:

assert(MyFunction() == std::vector<int>{1, 3, 4}); // <- this.

3

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

#define VECTOR(first,...) \
   ([](){ \
   static const decltype(first) arr[] = { first,__VA_ARGS__ }; \
   std::vector<decltype(first)> ret(arr, arr + sizeof(arr) / sizeof(*arr)); \
   return ret;})()

ฟังก์ชั่นตัวอย่าง

template<typename T>
void test(std::vector<T>& values)
{
    for(T value : values)
        std::cout<<value<<std::endl;
}

ตัวอย่างการใช้งาน

test(VECTOR(1.2f,2,3,4,5,6));

แม้ว่าจะระมัดระวังเกี่ยวกับเดคประเภทให้แน่ใจว่าค่าแรกเป็นสิ่งที่คุณต้องการอย่างชัดเจน


3

มีหลายวิธีในการฮาร์ดโค้ดเวกเตอร์ฉันจะแบ่งปันวิธีการบางอย่าง:

  1. เริ่มต้นโดยการผลักดันค่าหนึ่งโดยหนึ่ง
// Create an empty vector 
    vector<int> vect;  

    vect.push_back(10); 
    vect.push_back(20); 
    vect.push_back(30); 
  1. กำลังเริ่มต้นเช่นอาร์เรย์
vector<int> vect{ 10, 20, 30 };
  1. กำลังเริ่มต้นจากอาร์เรย์
    int arr[] = { 10, 20, 30 }; 
    int n = sizeof(arr) / sizeof(arr[0]); 

    vector<int> vect(arr, arr + n); 
  1. การเริ่มต้นจากเวกเตอร์อื่น
    vector<int> vect1{ 10, 20, 30 }; 

    vector<int> vect2(vect1.begin(), vect1.end()); 

2

"ฉันจะสร้างเวกเตอร์ STL ได้อย่างไรและเริ่มต้นมันเหมือนด้านบน? วิธีที่ดีที่สุดในการทำเช่นนั้นคือความพยายามพิมพ์ขั้นต่ำคืออะไร"

วิธีที่ง่ายที่สุดในการเริ่มต้นเวกเตอร์ที่คุณได้เริ่มต้นของคุณในตัวอาร์เรย์จะใช้รายการ initializer ซึ่งเป็นที่รู้จักใน C

// Initializing a vector that holds 2 elements of type int.
Initializing:
std::vector<int> ivec = {10, 20};


// The push_back function is more of a form of assignment with the exception of course
//that it doesn't obliterate the value of the object it's being called on.
Assigning
ivec.push_back(30);

ivec คือขนาด 3 องค์ประกอบหลังจากดำเนินการมอบหมาย (คำสั่งที่มีข้อความ)


ในบรรทัดที่คล้ายกันฉันพยายามเริ่มต้นแผนที่ std :: map <int, bool> catinfo = {{1, false}}; แต่จากนั้นได้รับข้อผิดพลาดนี้: ใน C ++ 98 'catinfo' จะต้องเริ่มต้นโดยนวกรรมิกไม่ใช่โดย '{... }'
pdk

2

B. Stroustrup อธิบายวิธีที่ดีในการปฏิบัติการลูกโซ่ใน16.2.10 Selfreferenceในหน้า 464 ในรุ่น C ++ 11 ของ Prog หรั่ง โดยที่ฟังก์ชันส่งคืนการอ้างอิงที่นี่ถูกดัดแปลงเป็นเวกเตอร์ วิธีนี้คุณสามารถเชื่อมโยงเหมือนกันv.pb(1).pb(2).pb(3);แต่อาจทำงานได้มากเกินไปสำหรับกำไรเล็กน้อย

#include <iostream>
#include <vector>

template<typename T>
class chain
{
private:
    std::vector<T> _v;
public:
    chain& pb(T a) {
        _v.push_back(a);
        return *this;
    };
    std::vector<T> get() { return _v; };
};

using namespace std;

int main(int argc, char const *argv[])
{
    chain<int> v{};

    v.pb(1).pb(2).pb(3);

    for (auto& i : v.get()) {
        cout << i << endl;
    }

    return 0;
}

1
2
3


ไลบรารีตัวนิ่มทำเพื่อเมทริกซ์การเริ่มต้น แต่ใช้ตัวดำเนินการ << แทนฟังก์ชันที่ระบุชื่อ: arma.sourceforge.net/docs.html#element_initialisation
Agnel Kurian

0

วิธีที่ง่ายที่สุดและถูกหลักสรีรศาสตร์มากขึ้น (ด้วย C ++ 11 หรือใหม่กว่า):

auto my_ints = {1,2,3};

0

ในกรณีที่คุณต้องการมีไว้ในชั้นเรียนของคุณ:

#include <initializer_list>
Vector<Type>::Vector(std::initializer_list<Type> init_list) : _size(init_list.size()),
_capacity(_size),
_data(new Type[_size])
{
    int idx = 0;
    for (auto it = init_list.begin(); it != init_list.end(); ++it)
        _data[idx++] = *it;
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.