2009-04-25 39 views
7

Tôi muốn có thể khởi tạo một vectơ có kích thước 'SIZE' trước chính. Thông thường, tôi sẽ làmKhởi tạo một vectơ trước main() trong C++

static vector<int> myVector(4,100); 

int main() { 

    // Here I have a vector of size 4 with all the entries equal to 100 

} 

Nhưng vấn đề là tôi muốn khởi tạo mục đầu tiên của véc tơ có giá trị nhất định và giá trị kia sang giá trị khác.

Có cách nào dễ dàng để thực hiện việc này không?

+0

Điều gì về điều này: std :: vector a (3, 100), & a_init ((a [0] = 98, a [1] = 99, a)); nó sẽ làm cho bằng "98, 99, 100" :) –

+1

Chỉ vì tò mò, tại sao bạn cần nó? –

Trả lời

6

Đây là giải pháp thay thế :

#include <vector>     
static std::vector<int> myVector(4,100); 

bool init() 
{ 
    myVector[0] = 42;  
    return true; 
} 

bool initresult = init(); 

int main()     
{ 
    ; 
} 
+0

Thú vị ... Có thể nào đó không lãng phí không gian bool? – Unknown

+0

Có, nhưng không thực sự. bạn có thể thử nhúng initcall ở đâu đó, nhưng điều đó sẽ "ẩn" nó: int somevalue = (init(), 42); –

+0

Cũng lưu ý rằng tĩnh không được dùng làm thông báo cho liên kết "nội bộ" (nghĩa là chỉ trong đơn vị dịch). Sử dụng một không gian tên ẩn danh để thay thế. – Macke

20

Hãy thử điều này:

static int init[] = { 1, 2, 3 }; 
static vector<int> vi(init, init + sizeof init/sizeof init[ 0 ]); 

Ngoài ra, xem std::generate (nếu bạn muốn khởi tạo trong một hàm).

+1

Đây không chỉ là cách rõ ràng nhất, mà còn là cách nhanh nhất và rõ ràng nhất. 1 (ít nhất là nếu các mục khác đều bằng không) –

+0

không, điều này sẽ cung cấp cho một véc tơ 3 mặt hàng (không có yếu tố phụ), nhưng cho rằng, nó khá gọn gàng. – Macke

7

Một chút hackish, nhưng bạn có thể làm điều này:

struct MyInitializer { 
    MyInitializer() { 
     myVector[0]=100; 
     //... 
    } 
} myInitializer; // This object gets constructed before main() 
+0

hackish, và một chút nguy hiểm vì bạn không thể bắt ngoại lệ trước khi chính, nhưng chính xác những gì tôi làm trong những trường hợp này là tốt. –

+0

@Nils: Trên thực tế, lớp véc tơ cung cấp một ctor dựa trên vòng lặp có thể được kết hợp với các mảng cho loại điều này. An toàn hơn nhiều, IMO. – dirkgently

9

Hoặc chỉ cần tạo một hàm và gọi đó là:

std::vector<int> init() 
{ 
    ... 
} 

static std::vector<int> myvec = init() 

Một chút không hiệu quả có lẽ, nhưng điều đó có thể không quan trọng với bạn bây giờ, và với C++ 0x và di chuyển nó sẽ rất nhanh.

Nếu bạn muốn tránh các bản sao (đối với C++ 03 trở về trước), sử dụng một thông minh-con trỏ:

std::vector<int>* init() { 
    return new std::vector<int>(42); 
} 

static boost::scoped_ptr<std::vector<int>> myvec(init()); 
0

Wrap nó bằng một lớp:

class SpecialVector 
{ 
    public: 
    SpecialVector() 
    { 
     myVector[0] = 1; 
     myVector[1] = 4; 
     // etc. 
    } 
    const vector<int> & GetVector() const 
    { 
     return myVector; 
    } 
    private: 
    vector<int> myVector; 
}; 
static SpecialVector SpVec; 

int main() { 
} 
+0

lý do tại sao tại sao ..... –

+0

toàn cầu tĩnh là xấu .... a-void chúng nếu bạn có thể! không có cách nào để bắt ngoại lệ, valgrind nghĩ rằng đó là một rò rỉ, khó gỡ lỗi nếu có một ngoại lệ về thoát ứng dụng! –

9

C++ 0x sẽ cho phép danh sách trình khởi tạo cho vùng chứa chuẩn, giống như tổng hợp:

std::vector<int> bottles_of_beer_on_the_wall = {100, 99, 98, 97}; 

Rõ ràng chưa đạt tiêu chuẩn, nhưng được cho là được hỗ trợ từ GCC 4.4. Tôi không thể tìm thấy tài liệu cho nó trong MSVC, nhưng Herb Sutter đã nói rằng hỗ trợ C++ 0x của họ là đi trước ủy ban ...

3

Thay vì sử dụng toàn cầu, tôi khuyên bạn nên sử dụng tĩnh cục bộ. Khi khởi tạo của vectơ của bạn diễn ra trước khi chính được nhập bất kỳ trường hợp ngoại lệ ném sẽ không bị bắt bởi chính. Nói ví dụ, bạn có một loại mà khi nó được xây dựng có thể ném một ngoại lệ:

class A { 
public: 
    A() { 
    // ... code that might throw an exception 
    } 
}; 

Đối với khởi sau, try/catch trong cơ thể của chính sẽ không bắt các ngoại lệ ném ra bởi các nhà xây dựng, vv của bạn chương trình đơn giản sẽ chết ngay lập tức và thậm chí bạn sẽ không thể sử dụng trình gỡ rối để tìm ra nguyên nhân!

std::Vector<A> v(5, A()); // May throw an exception here not caught by main 

int main() { 
    try { 
    // Exception for 'v' not handled here. 
    } 
    catch (...) { 
    } 
} 

Một phương pháp khác mà sẽ bắt một ngoại lệ từ các nhà xây dựng là sử dụng một tĩnh địa phương - được khởi tạo bằng cách sử dụng kỹ thuật được đề xuất bởi answer này.

std::Vector<A> init(); // Returns a vector appropriately initialized 

std::vector<A> & getV() { 
    static std::vector<A> cache = init(); 
    return cache; 
} 

int main() { 
    try { 
    getV().at[0]; // First call to getV - so initialization occurs here! 
    } 
    catch (...) { 
    } 
} 
Các vấn đề liên quan