2013-09-24 67 views
5

Bị kẹt trong chức năng xóa trên bài tập 11 ch 11 11. Tôi đã phá hủy các đối tượng nhưng tôi không có ý tưởng làm thế nào để sử dụng deallocation từ thư viện cấp phát để trả lại không gian.Tập thể dục tăng tốc C++ 11-6

Vui lòng gửi tiền cho tôi. PS: không phải bài tập về nhà nhưng tôi đang thực hành ở nhà

Dưới đây là mã từ Tăng tốc C++ và sau đó là chức năng xóa sửa đổi của tôi. Cảm ơn '

template <class T> class Vec 
{ 
public: 
    typedef T* iterator; 
    typedef const T* const_iterator; 
    typedef size_t size_type; 
    typedef T value_type; 
    typedef T& reference; 
    typedef const T& const_reference; 

    Vec() { create(); } 
    explicit Vec(size_type n, const T& t = T()) { create(n, t); } 
    Vec(const Vec& v) { create(v.begin(), v.end()); } 
    Vec& operator=(const Vec&); 
    ~Vec() { uncreate(); } 

    T& operator[](size_type i) { return data[i]; } 
    const T& operator[](size_type i) const { return data[i]; } 

    void push_back(const T& t) 
    { 
     if (avail == limit) 
     { 
      grow(); 
     } 

     unchecked_append(t); 
    } 

    iterator erase(iterator); 
    iterator erase(iterator, iterator); 
    void clear(); 

    size_type size() const { return avail - data; } 

    iterator begin() { return data; } 
    const iterator begin() const { return data; } 

    iterator end() { return avail; } 
    const iterator end() const { return avail; } 

private: 
    iterator data; 
    iterator avail; 
    iterator limit; 

    std::allocator<T> alloc; 

    void create(); 
    void create(size_type, const T&); 
    void create(const_iterator, const_iterator); 

    void uncreate(); 

    void grow(); 
    void unchecked_append(const T&); 
}; 

MY MÃ

template <class T> typename Vec<T>::iterator Vec<T>::erase(iterator first, iterator second) 
{ 
    if(second < first) 
    { 
     throw std::out_of_range("Iterator out of bounds."); 
    } 
    if(first < data || second >= avail) 
    { 
     throw std::out_of_range("Iterator out of bounds."); 
    } 
    iterator last = avail -1 ; 
    iterator i = first ; 
    iterator j = second ; 
    while(j <= last) 
    { 
     *i++ = *j++ ; 

    } 
    // destroy each initilsed space 
    iterator new_avail = avail - first + second ; 

    std::cout << " end " << end() << std::endl; 

    while(avail != new_avail) 
    { 
     alloc.destroy(--avail) ; 
    } 


    // dellocate space how to do that ? 
    alloc.deallocate(avail -1, ); // not sure what to do here 
    return first ; 

} 
+0

Bạn đang thực sự cố gắng làm gì? – thecoshman

Trả lời

4

Bạn không thể phân phối một phần bộ nhớ được cấp phát. Điều đó

alloc.deallocate (avail -1,);

không tốt.

Sửa

Bạn không nên cố gắng mangage phân bổ trong xóa. Một tùy chọn bạn có là phân bổ lại nó, điều này sẽ làm cho việc xóa nhiều hơn tốn kém. Chức năng thứ hai có thể làm:

iterator shrink(iterator first, iterator last) { 

    size_type capacity = (limit - data) - (last - first); 

    iterator new_data = alloc.allocate(capacity); 
    iterator new_avail = new_data; 
    iterator source = data; 
    while(source < first) 
     // C++11 
     alloc.construct(new_avail++, std::move(*source++)); 
    source = last; 
    iterator result = new_avail; 
    while(source < avail) 
     // C++11 
     alloc.construct(new_avail++, std::move(*source++)); 
    while(data < avail) 
     alloc.destroy(--avail); 
    data = new_data; 
    avail = new_avail; 
    limit = new_data + capacity; 

    return result; 
} 

Tùy chọn tốt hơn là cách tiêu chuẩn này. Thêm một nhà xây dựng bổ sung, swap và shrink_to_fit:

Vec(const_iterator first, const_iterator last) { 
    create(first, last); 
} 

void swap(Vec& other) { 
    std::swap(data, other.data); 
    ... 
} 

bool shrink_to_fit() { 
    try 
    { 
     Vec(begin(), end()).swap(*this); 
     return true; 
    } 
    catch(...) {} 
    return false; 
} 

Bây giờ bạn có thể áp dụng nhiều thao tác trên vectơ và thu nhỏ tiêu thụ bộ nhớ cuối cùng.

v.erase(a, b); 
v.erase(c, d); 
... 
v.shrink_to_fit(); 
2

Tôi cho rằng, đó là một trong những giải pháp là tạo ra một vector mới với kích thước sau:

new_size = old_size - number_of_elements_to_delete 

Sau đó, bạn sao chép các đối tượng từ đầu đối tượng xóa đầu tiên, từ đối tượng xóa cuối cùng đến cuối và sau đó giải phóng vectơ cũ.

Nó không phải là giải pháp tốt nhất nhưng đơn giản nhất như tôi nghĩ.

+0

Cảm ơn bạn đã trả lời, tôi đoán những gì tôi đang làm cũng không phải là xấu, tôi chỉ không knwo làm thế nào để sử dụng chức năng thành viên deallocate từ cấp phát. Vì vậy, chủ yếu là tôi cần giúp đỡ trong đó. Cảm ơn – samprat

2

Đây là những gì một reference page for std::allocator::deallocate đã có nói:

void deallocate(pointer p, size_type n);

deallocates lưu trữ tham chiếu bởi con trỏ p, mà phải là một con trỏ thu được bằng một cuộc gọi trước đó để allocate(). Đối số n phải bằng đối số thứ hai của cuộc gọi đến allocate() mà ban đầu được sản xuất p.

Tức là, bạn không thể phân bổ một phần dung lượng mà bạn đã phân bổ, chỉ toàn bộ đoạn.

Giải pháp sẽ không trả lại dung lượng được thực hiện miễn phí bằng cách gọi tới erase. Chỉ cần cập nhật trình lặp thành viên của bạn sao cho phù hợp để bạn giữ bộ nhớ này khả dụng cho các cuộc gọi tiếp theo tới create. Đây là những gì các container tiêu chuẩn vector nào, quá.

Nếu bạn thực sự muốn trả lại bộ nhớ dư, hãy phân bổ đoạn tạm thời nhỏ hơn, sao chép các phần tử đang ở trong vùng chứa đó, giải phóng bộ nhớ cũ và cập nhật trình lặp.

Điều cần lưu ý ở đây là an toàn ngoại lệ. Khi bạn cấp phát bộ đệm tạm thời, bạn cần đảm bảo rằng bạn không bị rò rỉ bộ đệm trong trường hợp ngoại lệ xảy ra trong khi sao chép các phần tử.

2

Như jrok và những người khác đã đề cập, bạn không thể giải quyết một phần bộ nhớ - bạn sẽ cần phải deallocate entire referenced storage. Có một điều quan trọng hơn - nếu bạn xem qua Chương 11 (cụ thể, dưới 11.4, Dynamic Vecs), bạn sẽ nhận thấy rằng việc triển khai cho push_back() tăng gấp đôi kích thước của mảng cơ bản sau khi đạt đến mức tối đa hiện tại kích thước.

Mở đường tương tự, bạn muốn Halve kích thước của mảng tiềm ẩn khi kích thước của vector của bạn trở nên một phần tư của kích thước tối đa hiện hành. Đây là thời điểm bạn cần phải phân bổ lại bộ nhớ và gọi std::allocator::deallocate để giải phóng bộ nhớ dư thừa.

Các vấn đề liên quan