2017-02-22 14 views
7

Giả sử tôi có hàm API thư viện C, con trỏ của con trỏ là tham số. Tuy nhiên kể từ khi tôi lập trình trong C + + tôi muốn tận dụng lợi thế của vector std để đối phó với bộ nhớ động. Làm thế nào tôi có thể chuyển đổi hiệu quả vector vectơ thành con trỏ của con trỏ? Ngay bây giờ tôi đang sử dụng này.Chuyển đổi vectơ của vectơ thành con trỏ của con trỏ

#include <vector> 

/* C like api */ 
void foo(short **psPtr, const int x, const int y);  

int main() 
{ 
    const int x = 2, y = 3; 
    std::vector<std::vector<short>> vvsVec(x, std::vector<short>(y, 0)); 
    short **psPtr = new short*[x]; 

    /* point psPtr to the vector */ 
    int c = 0; 
    for (auto &vsVec : vvsVec) 
     psPtr[c++] = &vsVec[0]; 

    /* api call */ 
    foo(psPtr, x, y);   

    delete[] psPtr; 
    return 0; 
} 

Đây có phải là cách tốt nhất để đạt được mục tiêu không? Tôi có thể loại bỏ điều "xóa mới" bằng cách sử dụng trình lặp hoặc phương thức std nào đó trong trường hợp này không? Cảm ơn trước.

Chỉnh sửa: Theo câu trả lời Tôi hiện đang sử dụng phiên bản này để giao tiếp với mã C. Tôi đăng nó ở đây.

#include <vector> 

/* C like api */ 
void foo(short **psPtr, const int x, const int y);  

int main() 
{ 
    const int x = 2, y = 3; 
    std::vector<std::vector<short>> vvsVec(x, std::vector<short>(y, 0)); 
    std::vector<short*> vpsPtr(x, nullptr); 

    /* point vpsPtr to the vector */ 
    int c = 0; 
    for (auto &vsVec : vvsVec) 
     vpsPtr[c++] = vsVec.data(); 

    /* api call */ 
    foo(vpsPtr.data(), x, y);   

    return 0; 
} 

Có vẻ như C++ giống với tôi hơn. Cảm ơn vì tất cả!

+3

Thả một mức độ vector và lấy địa chỉ của một con trỏ đến phần tử đầu tiên của rằng vector phẳng. – rubenvb

+0

Chỉ làm cho nó trông đẹp hơn, bạn có thể thay thế psPtr bằng một vector và thiết lập nó bằng một số hàm trong thuật toán. – BlueWanderer

+0

Hàm API cần tham số kích thước hoặc có quy ước rằng một con trỏ rỗng biểu thị phần tử cuối cùng, trong trường hợp này bạn phải thêm một 'nullptr' vào cuối. –

Trả lời

4

Đây có phải là cách tốt nhất để đạt được mục tiêu không?

Nếu bạn chắc chắn rằng vectơ của vectơ sẽ vượt trội hơn psPtr, thì có. Nếu không, bạn chạy rủi ro psPtr sẽ chứa các con trỏ không hợp lệ.

Tôi có thể loại bỏ điều "xóa mới" bằng cách sử dụng trình lặp hoặc phương thức std nào đó trong trường hợp này không?

Có. Tôi khuyên bạn nên sử dụng:

std::vector<short*> psPtr(vvsVec.size()); 

và sau đó sử dụng &psPtr[0] trong khi gọi hàm C API. Điều đó loại bỏ gánh nặng quản lý bộ nhớ khỏi mã của bạn.

foo(&psPtr[0]);   
+0

Điều này trông khá gọn gàng. Không bao giờ nghĩ đến vector của con trỏ trước đây. Cảm ơn! – yc2986

+0

@ yc2986, bạn được chào đón. –

+0

@ yc2986: Một vectơ của con trỏ thường là kiểu chống. Nếu bạn không bao giờ nghĩ đến việc này, đây thực sự là một điều tốt. – IInspectable

3
std::vector<short*> vecOfPtrs; 
for (auto&& vec : vvsVec) 
    vecOfPtrs.push_back(&vec[0]); 

foo(&vecOfPtrs[0]); 
+0

Vì bạn biết kích thước của container 'vecOfPtrs' trước thời hạn, bạn nên thực sự khởi tạo nó với kích thước đó. Điều này ngăn cản việc di chuyển bộ nhớ tiềm năng và các ngoại lệ tiềm năng do thay đổi kích thước. – IInspectable

+0

Tại sao '& vec [0]' và không phải 'vec.data()'? Tôi có thể nghĩ ra ít nhất 3 lý do để sử dụng 'vec.data() 'over' & vec [0] ', và 0 để sử dụng' & vec [0] 'trên' vec.data() '. (vectơ trống, 'vectơ ', 'std :: vấn đề addressof', giảm tầm quan trọng) – Yakk

+0

@Yakk Tôi đoán thói quen cũ chết cứng từ C++ 03. 'vec.data()' là cấp trên. Tuy nhiên, lý do đầu tiên của bạn không tốt chút nào vì 'vec.data()' phải trả về '& vec [0]', ngay cả đối với một vectơ trống, và chuẩn C++ cho phép lấy địa chỉ của một đầu cuối của một mảng. – rlbond

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