2015-02-20 18 views
8

Tôi có một hộp đen C++ chức năng mà tôi không có quyền truy cập vào mã nguồn của nó:Tham chiếu đến phân đoạn một phần của vectơ?

void blackbox(vector<int> &input); 

chức năng này sửa đổi các yếu tố của vectơ đầu vào một cách rõ.

Vấn đề tôi có bây giờ là tôi chỉ muốn áp dụng chức năng hộp đen cho một phân đoạn một phần của vectơ, ví dụ, 500 phần tử cuối cùng của vectơ. Vì vậy, đây là thói quen mà tôi đã viết để đạt được mục tiêu này:

vector<int> foo (5,1000); 
vector<int> bar (foo.end()-500,foo.end()); 

blackbox(bar); 

swap_ranges(foo.end()-500,foo.end(),bar.begin()); 

Mã này có thể làm việc, nhưng là có một cách tốt hơn để làm điều này?

Sẽ tốt nếu tôi chỉ có thể xác định tham chiếu véc-tơ cho một đoạn một véc tơ hiện có, thay vì tạo bản sao. Tôi không cảm thấy thoải mái với việc sao chép và trao đổi các phần trong mã trên; vì thường lệ này là được gọi quá thường xuyên, tôi nghĩ việc sao chép lặp lại và trao đổi sẽ làm chậm mã. Nếu tôi biết các hoạt động chính xác được thực hiện bởi các khối hộp, tôi sẽ viết lại các chức năng để nó mất các vòng lặp vector như các đối số đầu vào . Thật không may, điều này là không thể vào lúc này.

+4

đó dụ minh họa cách tốt đẹp đó là để có thể vượt qua vòng lặp chức năng thay vì container. –

+0

Ngay cả khi bạn đã có mã nguồn, nó có thể không thể viết lại hàm để lấy vòng lặp làm đối số duy nhất của nó (ví dụ: nếu nó thực hiện chèn). – Beta

Trả lời

2

Không có cách nào được xác định rõ ràng để đạt được chức năng này. Với cảnh báo rất lớn và cảnh báo, nó có thể (đối với một phiên bản GCC ít nhất) bị tấn công như dưới đây, hoặc bạn có thể viết một cái gì đó với hành vi được xác định tốt hơn, nhưng dựa trên thực hiện std::vector của trình biên dịch của bạn ....

Vì vậy .. bị tấn công. Điều này sẽ không hoạt động nếu insert/erase/resize/reserve/clear/push_back hoặc bất kỳ hoạt động nào khác ảnh hưởng đến vectơ tổng thể được thực hiện. Nó có thể không được di động/tiếp tục làm việc/làm việc với tất cả các mức tối ưu hóa/làm việc vào thứ Ba/sử dụng có nguy cơ riêng vv .. Nó phụ thuộc vào việc tối ưu hóa lớp cơ sở trống.

Bạn cần một cấp phát tùy chỉnh nhưng có một nhược điểm: bộ cấp phát không thể có bất cứ tiểu bang hoặc nó sẽ thay đổi bố cục nhị phân của đối tượng vector, vì vậy chúng tôi kết thúc với điều này:

#include <iostream> 
#include <vector> 

template <typename Container> // easy to get this working... 
void f(Container& v) 
{ 
    std::cout << "f() v.data() " << v.data() << ", v.size() " << v.size() << '\n'; 
    for (int& n : v) n += 10; 
} 

void g(std::vector<int>& v) // hard to get this working... 
{ 
    std::cout << "g() v.data() " << v.data() << ", v.size() " << v.size() << '\n'; 
    for (int& n : v) n += 100; 
} 

int* p_; // ouch: can't be a member without changing vector<> memory layout 


struct My_alloc : std::allocator<int> 
{ 
    // all no-ops except allocate() which returns the constructor argument... 

    My_alloc(int* p) { p_ = p; } 

    template <class U, class... Args> 
    void construct(U* p, Args&&... args) { std::cout << "My_alloc::construct(U* " << p << ")\n"; } 

    template <class U> void destroy(U* p) { std::cout << "My_alloc::destroy(U* " << p << ")\n"; } 

    pointer allocate(size_type n, std::allocator<void>::const_pointer hint = 0) 
    { 
     std::cout << "My_alloc::allocate() return " << p_ << "\n"; 
     return p_; 
    } 
    void deallocate(pointer p, size_type n) { std::cout << "deallocate\n"; } 

    template <typename U> 
    struct rebind { typedef My_alloc other; }; 
}; 

int main() 
{ 
    std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 
    std::cout << "main() v.data() " << v.data() << '\n'; 
    My_alloc my_alloc(&v[3]); // first element to "take over" 
    std::vector<int, My_alloc> w(3, my_alloc); // num elements to "take over" 
    f(w); 
    g(reinterpret_cast<std::vector<int>&>(w)); 
    for (int n : v) std::cout << n << ' '; 
    std::cout << '\n'; 
    std::cout << "sizeof v " << sizeof v << ", sizeof w " << sizeof w << '\n'; 
} 

Output :

main() v.data() 0x9d76008 
My_alloc::allocate() return 0x9d76014 
My_alloc::construct(U* 0x9d76014) 
My_alloc::construct(U* 0x9d76018) 
My_alloc::construct(U* 0x9d7601c) 
f() v.data() 0x9d76014, v.size() 3 
g() v.data() 0x9d76014, v.size() 3 
0 1 2 113 114 115 6 7 8 9 
sizeof v 12, sizeof w 12 
My_alloc::destroy(U* 0x9d76014) 
My_alloc::destroy(U* 0x9d76018) 
My_alloc::destroy(U* 0x9d7601c) 
deallocate 

Xem nó chạy here

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