2010-08-14 13 views
54

Tôi có thể realloc bằng C++ bằng cách nào? Có vẻ như bị thiếu ngôn ngữ - có newdelete nhưng không phải là resize!Làm thế nào để bạn 'realloc' trong C + +?

Tôi cần vì chương trình của tôi đọc nhiều dữ liệu hơn, tôi cần phải phân bổ lại bộ đệm để giữ nó. Tôi không nghĩ rằng delete nhập con trỏ cũ và new nhập một cái mới, lớn hơn, là tùy chọn đúng.

+7

Stroustrup đã trả lời điều này một thời gian dài, xem: http://www2.research.att.com/~bs/bs_faq2.html#renew (Đó là một khởi đầu tốt nếu bạn mới dùng C++ cùng với Cline's C++ FAQ.) – dirkgently

+4

Câu trả lời được tham chiếu bởi @dirkgently hiện có tại: http://www.stroustrup.com/bs_faq2.html#renew - và Câu hỏi thường gặp của Cline hiện là một phần của Câu hỏi thường gặp về siêu: https://isocpp.org/faq – maxschlepzig

Trả lời

35

Sử dụng :: std :: vector!

Type* t = (Type*)malloc(sizeof(Type)*n) 
memset(t, 0, sizeof(Type)*m) 

trở thành

::std::vector<Type> t(n, 0); 

Sau đó

t = (Type*)realloc(t, sizeof(Type) * n2); 

trở thành

t.resize(n2); 

Nếu bạn muốn vượt qua con trỏ vào chức năng, thay vì

012.
Foo(t) 

sử dụng

Foo(&t[0]) 

Đó là hoàn toàn đúng C++, vì vector là một C-mảng thông minh.

+1

Không nên ghi nhớ dòng ghi nhớ (t, 0, sizeof (T) * n) ;? n thay vì m? – anthom

+1

@anthom yes. nó thực sự phải là 'Type * t = static_cast (malloc (n * sizeof * t)); ' –

+0

Với C++ 11, bây giờ ta sẽ sử dụng' t.data() 'thay vì' & t [0] ' – knedlsepp

39

Tùy chọn phù hợp có thể là sử dụng vùng chứa làm công việc cho bạn, như std::vector.

newdelete không thể thay đổi kích thước, vì chúng chỉ phân bổ đủ bộ nhớ để chứa đối tượng thuộc loại đã cho. Kích thước của một loại nhất định sẽ không bao giờ thay đổi. Có new[]delete[] nhưng hầu như không có lý do gì để sử dụng chúng.

realloc làm trong C có thể sẽ chỉ là một malloc, memcpyfree, dù sao, mặc dù các nhà quản lý bộ nhớ được phép làm điều gì đó thông minh nếu có đủ bộ nhớ trống liền kề có sẵn.

+0

Vì vậy, những gì sẽ là đúng cách để thực hiện một bộ đệm ngày càng tăng trong C + +? Hiện tại tôi có 'char * buf = (char *) malloc (size)', sau đó khi nó trở nên quá nhỏ, tôi làm 'buf = realloc (size + more_size); kích thước + = more_size'. Làm thế nào tôi có thể làm điều đó với vector? – bodacydo

+6

@ bodacydo: Không triển khai bộ đệm đang phát triển, chỉ cần sử dụng 'std :: vector' - nó sẽ tự động phát triển khi cần và bạn có thể cấp phát bộ nhớ nếu bạn muốn (' dự trữ() '). – sharptooth

+3

Sử dụng tiêu chuẩn :: vector . Đó là những gì nó cho. Trong C++, không có lý do gì để sử dụng new/delete/new []/delete [], trừ khi bạn đang viết một cách rõ ràng các lớp quản lý tài nguyên. – Puppy

29

Thay đổi kích thước trong C++ là khó xử vì nhu cầu tiềm năng để gọi hàm tạo và hàm hủy.

Tôi không nghĩ rằng có một lý do cơ bản tại sao trong C++ bạn không thể có một nhà điều hành resize[] đi với new[]delete[], mà đã làm một cái gì đó tương tự như sau:

newbuf = new Type[newsize]; 
std::copy_n(oldbuf, std::min(oldsize, newsize), newbuf); 
delete[] oldbuf; 
return newbuf; 

Rõ ràng oldsize sẽ được lấy ra từ một vị trí bí mật, giống như vậy là trong delete[]Type sẽ đến từ loại toán hạng. resize[] sẽ không thành công khi Loại không thể sao chép được - điều này là đúng, vì các đối tượng như vậy không thể di chuyển được. Cuối cùng, mã trên mặc định xây dựng các đối tượng trước khi gán chúng, mà bạn sẽ không muốn như là hành vi thực tế.

Có tối ưu hóa có thể ở đó newsize <= oldsize, để gọi hàm hủy đối với các đối tượng "quá giới hạn" của mảng mới được điều chỉnh và không làm gì khác.Tiêu chuẩn sẽ phải xác định liệu tối ưu hóa này có cần thiết hay không (như khi bạn resize() một véc tơ), được phép nhưng không được chỉ định, được phép nhưng phụ thuộc vào việc triển khai hoặc bị cấm.

Câu hỏi mà bạn nên tự hỏi là "thực sự hữu ích khi cung cấp điều này, và cũng được thiết kế đặc biệt để cung cấp vùng chứa có thể thay đổi kích thước (bộ nhớ tiếp giáp - yêu cầu đó được bỏ qua C++ 98 nhưng cố định trong C++ 03) đó là một phù hợp hơn so với mảng với C + + cách làm việc?

Tôi nghĩ câu trả lời được cho là rộng rãi "không". Nếu bạn muốn làm bộ đệm có thể thay đổi theo cách C, hãy sử dụng malloc/free/realloc, có sẵn trong C++. Nếu bạn muốn thực hiện các bộ đệm có thể định lại theo cách C++, hãy sử dụng một vectơ (hoặc deque, nếu bạn không thực sự cần bộ nhớ tiếp giáp). Đừng cố gắng kết hợp cả hai bằng cách sử dụng new[] cho bộ đệm thô, trừ khi bạn đang triển khai vùng chứa giống vectơ.

-4

thử một cái gì đó như thế:

typedef struct Board 
{ 
    string name; 
    int size = 0; 
}; 

typedef struct tagRDATA 
{ 
    vector <Board> myBoards(255); 

    // Board DataBoard[255]; 
    int SelectedBoard; 

} RUNDATA; 

Vector sẽ phàn nàn. Đó là lý do tại sao mảng, malloc và mới vẫn tồn tại.

+4

Không, đó không phải là lý do. Và tôi không thấy cách này trả lời câu hỏi theo bất kỳ cách nào. Hoặc tại sao bạn đang sử dụng 'typedef' ở khắp mọi nơi như thể bạn đang viết C. –