2010-03-11 100 views
14

Tôi có một vector được khai báo là một biến toàn cầu mà tôi cần để có thể sử dụng lại. Ví dụ, tôi đang đọc nhiều tệp dữ liệu, phân tích cú pháp dữ liệu để tạo các đối tượng sau đó được lưu trữ trong một vectơ.Sử dụng lại một vector trong C++

vector<Object> objVector(100); 

void main() 
{ 
while(THERE_ARE_MORE_FILES_TO_READ) 
{ 
    // Pseudocode 
    ReadFile(); 
    ParseFileIntoVector(); 
    ProcessObjectsInVector(); 
    /* Here I want to 'reset' the vector to 100 empty objects again */ 

} 

}

Tôi có thể thiết lập lại các vector là "objVector vector (100)" vì nó đã được ban đầu được phân bổ trên stack? Nếu tôi làm "objVector.clear()", nó loại bỏ tất cả 100 đối tượng và tôi sẽ có một vectơ có kích thước bằng 0. Tôi cần kích thước của nó là 100 ở đầu mỗi vòng lặp.

+0

Bạn có cần giữ đối tượng hoặc bạn muốn đặt lại chúng về trạng thái được tạo mặc định không? – Macke

+1

Trong ví dụ của bạn, objVector được cấp phát tĩnh. Nó không được cấp phát trên ngăn xếp. – Alan

+3

Kiểu trả về của hàm chính của bạn không chính xác. Trong C và C++ chính phải luôn luôn trả về int (nhưng nếu bạn không thực sự trả về bất cứ điều gì, C++ và C99 sẽ trả về 0 cho bạn tự động). – Tronic

Trả lời

4
vector<Object> objVector(100); 

int main() 
{ 
while(THERE_ARE_MORE_FILES_TO_READ) 
{ 
    // Pseudocode 
    ReadFile(); 
    ParseFileIntoVector(); 
    ProcessObjectsInVector(); 
    /* Here I want to 'reset' the vector to 100 empty objects again */ 
    objVector.clear(); 
    objVector.resize(100); 

} 
} 
+0

Điều đó đã làm được. Cảm ơn! – Blade3

+2

Vâng, tôi vẫn nghĩ swap() là cách giới thiệu để thực hiện loại công việc này. Xem mục 17 của STL hiệu quả: Sử dụng “thủ thuật trao đổi” để cắt giảm công suất dư thừa. làm rõ ràng và sau đó thay đổi kích thước thực sự chậm hơn - nó có các hoạt động phân bổ bộ nhớ bổ sung hơn swap() –

+2

Cắt giảm dung lượng dư thừa thường không mong muốn (đó là lý do tại sao stdlib không làm điều đó). Có một hit hiệu suất gây ra bởi phân bổ thường xuyên. Lợi ích hiệu suất được tìm kiếm bằng cách sử dụng lại vectơ cũng sẽ bị mất hoàn toàn. – Tronic

2

Gọi thay đổi kích thước ở đầu hoặc cuối của vòng lặp: http://www.cplusplus.com/reference/stl/vector/resize/

Điều đó sẽ làm những gì bạn muốn. Tuy nhiên, tôi khuyên bạn nên sử dụng các chức năng push và pop thay thế. Đó là không gian hiệu quả hơn và là cách Vector được dự định sẽ được sử dụng. Vectơ sẽ mở rộng và thu nhỏ khi cần thiết khi bạn đẩy (thêm) và bật (loại bỏ) các mục khỏi nó. Bằng cách đó bạn không phải lo lắng về kích thước hoặc nội dung của vectơ. Nó đơn giản trở thành một hàng đợi xử lý.

1

Đoạn mã sau nên thực hiện thủ thuật.

vector<Object> temp(100); 
objVector.swap(temp); 
+0

Điều đó không giúp gì nhiều vì bạn chỉ loại bỏ một véc tơ khác, nhưng bạn vẫn loại bỏ nó. –

+0

@Let_Me_Be: Điều này loại bỏ những gì bạn đã có, thay thế nó bằng 100 đối tượng được xây dựng mặc định - những gì OP yêu cầu. – UncleBens

+0

@Let_Me_Be: Tôi thực sự không hiểu rõ nhận xét của bạn. Bạn có thể làm rõ một chút? –

6
objVector.clear(); 
objVector.resize(100); 

Tuy nhiên, đây có lẽ là không được khuyến khích sử dụng các vector. Bạn có chắc chắn bạn không nên sử dụng push_back với vectơ ban đầu trống không? Làm thế nào bạn có thể chắc chắn rằng mỗi tập tin chứa chính xác 100 đối tượng, không nhiều không kém, như nó xuất hiện từ câu hỏi của bạn?

Vectơ có thể không cần phải là toàn cục. Tốt hơn để vượt qua mọi thứ xung quanh. Khi bạn nhìn thấy một loạt các hàm được gọi là không có tham số, sẽ rất khó nếu không thể theo dõi những gì đang diễn ra (bởi vì mọi người khác ngoài bạn - và kể cả bạn khi bạn quay lại mã này sau vài tháng - sẽ có không có ý tưởng những chức năng này sử dụng cho đầu vào và đầu ra là gì).

0

Gọi objVector.clear() để xóa các điểm dữ liệu trước đó, sau đó objVector.resize(100) để đổi kích thước thành kích thước phù hợp. Tuy nhiên, lưu ý rằng, điều này sẽ phân bổ 1 thể hiện của Object bằng cách sử dụng hàm tạo mặc định và sau đó là 100 bản sao của Object bằng cách sử dụng hàm tạo bản sao, có thể hoặc không thể là những gì bạn thực sự muốn. Theo tùy chọn, nếu Object là loại con trỏ, bạn có thể sử dụng objVector.resize(100, NULL) để tránh phân bổ có thể không mong muốn.

+0

Không có phân bổ không mong muốn sẽ diễn ra nếu 'Object' là một kiểu con trỏ, thông qua' NULL' để 'resize' là hoàn toàn dư thừa, vì điều tương tự sẽ xảy ra mà không có nó. –

+0

Ngoài ra, bạn xác nhận về hàm tạo bản sao là sai. Hàm khởi tạo mặc định sẽ được gọi mỗi lần, nghĩa là 100 lần. –

+0

@Konrad bạn nhầm lẫn vào điểm thứ hai. Mặc định có thể được gọi là 100 lần trong trường hợp của lớp chỉ có các hàm tạo ngầm, nhưng một ứng dụng thử nghiệm nhanh sẽ cho thấy rằng hàm tạo bản sao thực sự được gọi nếu được thực hiện. Tuy nhiên, tôi đã nhầm lẫn: hàm tạo mặc định được gọi một lần và hàm tạo bản sao được gọi là 100 lần, chứ không phải 99. – Dathan

11

Tôi có một vector được khai báo là biến toàn cầu mà tôi cần để có thể sử dụng lại.

Tại sao? Nó không rõ ràng từ mã của bạn tại sao biến phải là toàn cục. Tại sao bạn không thể khai báo nó bên trong vòng lặp? Sau đó, bạn không cần phải đặt lại, điều này sẽ được thực hiện tự động trong mỗi vòng lặp.

Để truy cập biến từ các phương pháp khác, hãy chuyển nó thành tham số (bằng cách tham chiếu, để bạn có thể sửa đổi nó). Có một biến toàn cầu hiếm khi là một giải pháp tốt.

Một cái gì đó khác: main phải không bao giờ có loại trả về void, đây là C++ không hợp lệ và nhiều trình biên dịch sẽ từ chối.

0

Vì bạn đang sử dụng hàm tạo mặc định cho "Đối tượng", tôi nghĩ bạn có thể dựa vào dung lượng của vector thay vì kích thước của nó. Vì vậy, khi bạn gọi clear(), rất có thể là bạn không thay đổi dung lượng được thiết lập bởi nhà xây dựng vector của bạn (bạn có thể chứa ít nhất 100 phần tử, chúng đã được phân bổ). Đọc về dung lượng, dự trữ và kích thước và cách chúng khác nhau (dự trữ là cuộc gọi bạn thực hiện để yêu cầu thay đổi dung lượng, tôi chỉ đang chỉ ra nó trong trường hợp bạn cần).

Dù sao, nếu bạn cần đặt lại đối tượng về trạng thái mặc định, thay vì dựa vào khả năng đặt lại toàn bộ đối tượng, bạn cũng có thể thực hiện cuộc gọi trên đối tượng có tên "đặt lại "để đặt chúng vào trạng thái đó, và gọi nó trước khi bạn tái xử lý bằng cách sử dụng các đối tượng tương tự. Hiệu suất-khôn ngoan, tôi không thấy nó như là bất kỳ khác nhau, và mã khôn ngoan nó có vẻ giống như một giải pháp sạch.

1

Trái ngược với các bài viết khác, cách hiệu quả nhất để làm điều này có lẽ là đây:

objVector.resize(0); 
objVector.resize(100); 

clear() giải phóng bộ nhớ của vector trên một số triển khai (hậu điều kiện chỉ được yêu cầu của nó là kích thước đó() = 0). thay đổi kích thước (0) duy trì dung lượng.

Mẹo trao đổi cũng gọi một phân bổ bộ nhớ không cần thiết. Vector tạm thời mà bạn trao đổi sẽ cấp phát một khối bộ nhớ mới và sau khi trao đổi, khối bộ nhớ cũ cũng được giải phóng. Hiệu suất phải tốt hơn nếu không có phân bổ bộ nhớ.

+0

Thực ra, tôi đã tra cứu nó. Trong khi trong C++ 03 cả '.clear()' và '.resize (0)' không thể gây ra sự tái phân bổ (vì điều đó sẽ bị vô hiệu '.begin()', mà C++ 03 không cho phép), C++ 0x dường như cho phép cả '.clear()' và '.resize (0)' tái phân bổ (vì bây giờ chúng có thể làm mất hiệu lực '.begin()'). Tất nhiên, sự phân bổ lại không ngụ ý thay đổi năng lực, vì vậy người ta không thể tranh luận rằng "vì khả năng sẽ không thay đổi, không có sự tái phân bổ xảy ra.", Tôi nghĩ vậy. –

+0

Sự thay đổi im lặng tạo ra '.resize (0)' và '.ear()' có thể tái phân bổ là cái này: http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects. html # 414 (thông báo rằng cả hai vẫn phải phân bổ lại cùng một lượng hoặc bộ nhớ lớn hơn như được lưu trữ trong dung lượng. Vì vậy, sẽ khá vô nghĩa nếu chúng phân bổ lại. Nhưng về mặt lý thuyết, chúng có thể, nếu tôi đọc chính xác). –

+0

Heh, điều này hóa ra phức tạp hơn tôi tưởng. Cảm ơn các ý kiến. – AshleysBrain

2

Tại sao bạn đang cố đặt lại biến toàn cầu? Chỉ cần phân bổ một vectơ mới mỗi lần qua vòng lặp và truyền vectơ vào các hàm bằng cách tham chiếu.

void ParseFileIntoVector(vector<Object> &vector); 
void ProcessObjectsInVector(const vector<Object> &vector); 

int main() 
{ 
while(THERE_ARE_MORE_FILES_TO_READ) 
{ 
    // Pseudocode 
    vector<Object> objVector(100); 
    ReadFile(); 
    ParseFileIntoVector(objVector); 
    ProcessObjectsInVector(objVector); 
} 
} 
0
Tôi có thể đặt lại vectơ thành "vector objVector (100)" vì ban đầu nó được phân bổ trên ngăn xếp không?
  1. Vectơ C++ không được cấp phát trên ngăn xếp. Ít nhất không trực tiếp. Một trong các tham số cho vector (và các mẫu STL khác) là cấp phát. Bạn có thể sử dụng phân bổ hồ bơi, phân bổ đống, v.v.

    Trên thực tế, std::vector<T> được đóng gói độc đáo vào mảng với thông tin bổ sung (chẳng hạn như kích thước và dung lượng). Nếu không, kích thước của vector phải được biết trước (không bắt buộc).

  2. Thực tế trong ví dụ trên std::vector<T> không nằm trên ngăn xếp nhưng trong phần dữ liệu của chương trình (hoặc cách được gọi trên nền tảng không phải ELF).

Vì vậy, câu hỏi là nếu bạn cần:

  • Một vector kích thước 100. Trong trường hợp này, vì nó đã được chỉ ra, có khả năng là bạn đang làm một cái gì đó kỳ lạ. Nhưng nó vẫn có thể theo cách tốt đẹp theo phương pháp resize.
  • Một vectơ công suất 100. Trong trường hợp này, có thể bạn không nên làm bất cứ điều gì vì các vectơ không co lại khả năng AFAIR.Và chắc chắn nó không phải là cần thiết như vector thay đổi năng lực của nó năng động.
Các vấn đề liên quan