Không có tính năng đặc biệt của ngôn ngữ cho phép bạn thực hiện việc này. Đôi khi việc theo dõi đối tượng được xử lý bằng cách lăn bộ cấp phát bộ nhớ của riêng bạn, nhưng điều này không hoạt động dễ dàng trên ngăn xếp.
Nhưng nếu bạn đang sử dụng chỉ ngăn xếp, nó thực sự làm cho vấn đề của bạn dễ dàng hơn, giả sử rằng các đối tượng đang được theo dõi là trên một sợi đơn. C++ tạo ra sự bảo đảm đặc biệt về thứ tự xây dựng và phá hủy trên stack. Đó là, thứ tự hủy diệt chính xác là ngược lại trật tự xây dựng.
Và vì vậy, bạn có thể tận dụng điều này để lưu trữ một con trỏ trong mỗi đối tượng, cộng với một con trỏ tĩnh để theo dõi con trỏ gần nhất. Bây giờ bạn có một đối tượng ngăn xếp đại diện như một danh sách liên kết.
template <typename T>
class Trackable
{
public:
Trackable()
: previous(current())
{
current() = this;
}
~Trackable()
{
current() = previous;
}
// External interface
static const T *head() const { return dynamic_cast<const T*>(current()); }
const T *next() const { return dynamic_cast<const T*>(previous); }
private:
static Trackable * & current()
{
static Trackable *ptr = nullptr;
return ptr;
}
Trackable *previous;
}
Ví dụ:
struct Foo : Trackable<Foo> {};
struct Bar : Trackable<Bar> {};
// :::
// Walk linked list of Foo objects currently on stack.
for(Foo *foo = Foo::head(); foo; foo = foo->next())
{
// Do kung foo
}
Bây giờ, phải thừa nhận đây là một giải pháp rất đơn giản. Trong một ứng dụng lớn, bạn có thể có nhiều ngăn xếp bằng cách sử dụng các đối tượng của bạn. Bạn có thể xử lý các ngăn xếp trên nhiều luồng bằng cách thực hiện current()
sử dụng ngữ nghĩa thread_local. Mặc dù bạn cần một số phép thuật để thực hiện công việc này, vì head()
sẽ cần phải trỏ vào sổ đăng ký các chủ đề và điều đó sẽ yêu cầu đồng bộ hóa.
Bạn chắc chắn không muốn đồng bộ hóa tất cả các ngăn xếp thành một danh sách duy nhất, vì điều đó sẽ giết khả năng mở rộng hiệu suất của chương trình của bạn.
Đối với yêu cầu kéo của bạn, tôi cho rằng đó là một chuỗi riêng biệt muốn đi qua danh sách. Bạn sẽ cần một cách để đồng bộ hóa như vậy mà tất cả các đối tượng xây dựng mới hoặc phá hủy bị chặn bên trong Trackable<T>
trong khi danh sách đang được lặp lại. Hoặc tương tự.
Nhưng ít nhất bạn có thể lấy ý tưởng cơ bản này và mở rộng nó theo nhu cầu của bạn.
Hãy nhớ rằng, bạn không thể sử dụng cách tiếp cận danh sách đơn giản này nếu bạn phân bổ động các đối tượng của mình. Cho rằng bạn sẽ cần một danh sách hai chiều.
Bạn cần số liệu thống kê nào? Nếu nó chỉ theo dõi số lượng cá thể sống, hãy xem xét lưu trữ một số nguyên nguyên duy nhất trên mỗi lớp và có thể tạo một trình bao RAII đơn giản để đếm (nghĩa là bạn chỉ cần đặt nó trong định nghĩa lớp và công việc được thực hiện). – paddy
Nếu sử dụng, [đây là một ví dụ đơn giản] (http://coliru.stacked-crooked.com/a/5a25d7a6a2ec18a0) về những gì tôi đang nói đến. Nó không cho phép bạn lặp lại hoặc tìm kiếm các đối tượng của bạn, nhưng nó không rõ ràng tại sao bạn muốn làm điều đó. Truy cập một ngăn xếp theo cách này có lẽ không phải là một ý tưởng tốt. Ví dụ này chỉ cung cấp số lượng đối tượng với chi phí rất thấp và an toàn chỉ. – paddy
Điều đó về cơ bản sẽ là bản cập nhật đẩy, nhưng được coi là quá đắt. – choeger