2009-06-19 46 views
6

Đây là lớp C++ mà tôi đã tạo bằng n số con trỏ.tạo nhiều con trỏ NULL cùng một lúc

class SomeClass 
{ 
private: 
     int* ptr1; 
     int* ptr2; 
     ... 
     int* ptrn; 

private: 
     // constructors, destructors, and methods 
}; 

Trong giai đoạn khởi, tôi muốn làm cho tất cả những người con trỏ trỏ tới NULL (hoặc làm cho con trỏ trỏ đến NULL theo mặc định khi chúng được khai báo) chứ không phải làm như vậy:

void SomeClass::MakePtrNull() 
{ 
     ptr1 = NULL; 
     ptr2 = NULL; 
     ... 
     ptrn = NULL; 
} 

Có bất kỳ phương pháp dễ dàng nào để hoàn thành mục tiêu này? Tôi chỉ tự hỏi nếu có bất kỳ cách nào để tránh gõ n dòng ptr = NULL; trong chức năng của tôi. Cảm ơn trước.

THÊM dựa trên các câu trả lời mà tôi đã nhận được cho đến nay: Thật không may, những con trỏ phải được tách biệt, vì chúng được sử dụng cho các mục đích khác nhau. Tôi đã tạo ra tên của các con trỏ như vậy chỉ để làm cho một điểm của những gì tôi đang cố gắng để làm, nhưng mỗi con trỏ có một mục đích hoàn toàn khác nhau. Tôi đoán tôi sẽ phải làm cho họ trỏ đến NULL như tôi đã làm rồi. Cảm ơn câu trả lời của bạn.

+0

Lưu ý rằng nếu lớp không có người dùng khai báo hàm tạo, SomeClass() sẽ có tất cả con trỏ bằng không. Điều đó có nghĩa rằng bạn chỉ có thể làm * this = SomeClass(); và nó sẽ làm cho tất cả các con trỏ trỏ tới con trỏ null. –

+0

@litb, trong các thử nghiệm của tôi, chỉ các trường hợp tĩnh của SomeClass có tất cả các con trỏ được đánh số không; trường hợp tự động và heap nhận được bất cứ điều gì đã được nằm xung quanh trong ngăn xếp hoặc đống. –

+0

giả sử không có hàm tạo do người dùng khai báo, sau đó SomeClass() được khởi tạo như trái ngược với "a" trong {SomeClass a; }. Giá trị SomeClass() khởi tạo, đệ quy, tất cả các thành viên của nó. Điều này sẽ làm cho bất kỳ thành viên trỏ đến con trỏ null. Nếu bạn định nghĩa một biến tự động, và nó không có một hàm tạo khai báo người dùng, nó không được khởi tạo. Bạn sẽ phải làm ví dụ {SomeClass a = SomeClass(); } –

Trả lời

6

Tại sao bạn không sử dụng mảng hoặc vectơ thay vì tạo n con trỏ được đặt tên riêng? Sau đó, bạn có thể làm nulling trong một vòng lặp ngắn.

5

Bạn có thể làm điều này:

void SomeClass::MakePtrNull() 
{ 
     ptr1 = ptr2 = ptr3 = ... = ptrn = NULL; 
} 
3

Thứ nhất, kỹ thuật mà không công việc:

Calling memset để thiết lập toàn bộ đối tượng bằng không sẽ không làm. Đầu tiên, nó sẽ gây ra rất nhiều rắc rối nếu hàm của bạn có một hoặc nhiều hàm ảo, và thứ hai, một con trỏ null không được bảo đảm được biểu diễn bằng một mẫu bit của tất cả các số không.

Điều tôi có thể làm trong trường hợp của bạn là lưu trữ các con trỏ trong một mảng hoặc một vectơ. Sau đó, bạn có thể sử dụng chức năng std::fill để đặt tất cả thành NULL. (Hoặc bạn có thể sử dụng vòng lặp nếu bạn thích)

Tất nhiên, nếu bạn cần thực hiện việc này thường xuyên, có thể viết một lớp bao bọc hoạt động như con trỏ, nhưng đặt nó thành NULL theo mặc định của nó constructor.

Hoặc bạn có thể sử dụng tăng :: tùy chọn hoạt động cơ bản như thế này. (Mặc dù nó không phải là cụ thể đối với con trỏ)

+1

Bạn nói rằng một con trỏ null không được bảo đảm để được trình bày bởi một mẫu bit của tất cả các số không, điều đó ngụ ý rằng nếu một kiểm tra như thế này: nếu (ptr1) không phải là một cách an toàn để xác định con trỏ không phải là null ? –

+0

Có, vui lòng giải thích chi tiết về kịch bản 0x0 không phải là địa chỉ 'không có bộ nhớ được phân bổ tại đây' hợp lệ. Ngoài ra, nếu cấu trúc/lớp (cũng như các lớp cha mẹ của nó) không có phương thức ảo thì kích thước của nó sẽ chính xác là tổng của các kích thước của các thành viên. –

+1

@average. Đó là an toàn. Một ptr NULL phải đánh giá sai, nhưng việc thực hiện có thể đại diện cho nó trong bộ nhớ tuy nhiên nó thích. Trong thực tế, hầu hết mọi người đều sử dụng 0, bởi vì một NULL ptr cũng phải đúc thành số nguyên là 0 và nó thường dễ nhất và hiệu quả nhất không thay đổi mẫu bit. @ Shane: cấu trúc cần phải là POD cho những gì bạn nói để được đảm bảo theo tiêu chuẩn. Có những thứ khác so với các phương thức ảo có thể gây ra cấu trúc không phải là POD và có bất kỳ lớp cơ sở nào là một trong số chúng. –

2

Tại sao không sử dụng một constructor mặc định:

SomeClass::SomeClass() : ptr1(NULL), ptr2(NULL), ... 
{ 

} 

Bạn cũng có thể làm:

ptr1 = ptr2 = ptr3 = NULL; 
0

Sử dụng một vector cho điều này (vì bởi các âm thanh của bạn sẽ không cần chỉnh sửa danh sách trong tương lai - và bạn cần truy cập ngẫu nhiên). Bạn có thể làm điều đó như thế này:

class PointerList 
{ 
private: 
    typedef std::vector<int*> IntPtrVector; 
    IntPtrVector m_ptrVec; 

public: 
    PointerList() 
    { 
     m_ptrVec.reserve(5); 
     for (int i = 0; i < 5; i++) 
      m_ptrVec.push_back(NULL); 
    } 

    int* getPointer(int index) 
    { 
     return m_ptrVec[index]; 
    } 

    void setPointer(int index, int* ptr) 
    { 
     assert(index <= 4); 
     m_ptrVec[index] = ptr; 
    } 
}; 

EDIT

Mặc dù phải trung thực này sặc mùi ghettoness. Bạn có chắc chắn rằng vấn đề của bạn yêu cầu giải pháp này? Nếu bạn giải thích thêm về vấn đề cụ thể của bạn, trong một câu hỏi khác có lẽ, tôi chắc chắn bạn có thể nhận được một số câu trả lời tốt hơn về cách thực hiện những gì bạn muốn thanh lịch hơn - thay vì sau đó bằng cách tạo ra một vấn đề thứ hai.

+0

Toàn bộ vấn đề đặt ra là hỏi xem liệu tôi có thể thực hiện một cách lười biếng hay không. Cảm ơn thời gian của bạn trên các đề xuất mặc dù. – stanigator

11

Thay vì int *, tạo ra một lớp thông minh-con trỏ giống như đặc điểm giống hệt như một int *, nhưng mặc định-cấu trúc với NULL:

template <typename T> 
class MyPointer { 
    T *p; 

public: 
    MyPointer() : p(NULL) { } 
    MyPointer(T *o) : p(o) { } 
    operator T*() const { return p; } 
    // ...and the rest of the traditional smart-pointer operators 
}; 

Sau đó, sử dụng nó trong lớp học của bạn:

class SomeClass 
{ 
private: 
     MyPointer<int> ptr1; 
     MyPointer<int> ptr2; 
     ... 
     MyPointer<int> ptrn; 

private: 
     // constructors, destructors, and methods 
}; 

Mọi biến của loại MyPointer<int> sẽ được tự động khởi tạo chính xác trong các hàm tạo của SomeClass mà không cần nhập thêm bất kỳ. Nếu bạn không quên hoặc thực hiện không chính xác bất kỳ phương thức nào của MyPointer, nó sẽ hoạt động giống như một con trỏ bình thường và có cùng kích thước và hiệu suất chính xác.

+2

+1 để sử dụng hệ thống kiểu để thể hiện chính xác mục đích lập trình. –

+0

Một lợi ích khác là bạn và người bảo trì mã sẽ không cần phải khởi tạo con trỏ trong mọi hàm tạo, hoặc nhớ cập nhật danh sách khởi tạo nên số hoặc tên của các thành viên MyPointer thay đổi. –

+0

Ngoài ra - 0 thời gian chạy trên không – Eclipse

1

Bạn có thể đặt con trỏ vào cấu trúc và sau đó memset() cấu trúc khi cần. Các con trỏ vẫn được tách ra, nhưng bạn có phương tiện nhắm mục tiêu chúng như là một đơn vị duy nhất mà không ảnh hưởng đến phần còn lại của lớp học của bạn. Ví dụ:

struct MyPointers 
{ 
    int* ptr1; 
    int* ptr2; 
    ... 
    int* ptrn; 
}; 

class SomeClass 
{ 
private: 
    MyPointers ptrs; 
    ... 
}; 

void SomeClass::MakePtrNull() 
{ 
    memset(&ptrs, 0, sizeof(ptrs)); 
} 
+1

memset không hoạt động như thế này. xem câu trả lời của jalf. –

3

tôi khuyên bạn nên làm như sau, nếu bạn có để giữ con trỏ riêng (có lẽ là nhu cầu cấp bách nhất là nếu các con trỏ có thể có các loại khác nhau)

class SomeClass { 
    struct Pointers { 
     int* ptr1; 
     int* ptr2; 
     float* ptrn; 
    } ptrs; 

public: 
    void MakePtrNull(); 
}; 

void SomeClass::MakePtrNull() 
{ 
    // clears all pointers at once 
    ptrs = Pointers(); 
} 

này không hoạt động, bởi vì việc khởi tạo giá trị cho các lớp không có một hàm tạo khai báo người dùng sẽ làm giá trị khởi tạo tất cả các thành viên của nó. Giá trị khởi tạo của một con trỏ sẽ tạo ra một con trỏ null.

+0

Đó là một kỹ thuật tuyệt vời. +1 –

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