Một con trỏ thông minh là gì và khi nào tôi nên sử dụng một con trỏ?
Một con trỏ thông minh là gì và khi nào tôi nên sử dụng một con trỏ?
Câu trả lời:
CẬP NHẬT
Câu trả lời này khá cũ và mô tả những gì "tốt" vào thời điểm đó, đó là những gợi ý thông minh được cung cấp bởi thư viện Boost. Kể từ C ++ 11, các thư viện chuẩn đã được cung cấp đủ con trỏ thông minh loại, và vì vậy bạn nên ủng hộ việc sử dụng std::unique_ptr
, std::shared_ptr
và std::weak_ptr
.
Cũng có std::auto_ptr
. Nó rất giống với một con trỏ có phạm vi, ngoại trừ việc nó cũng có khả năng nguy hiểm "đặc biệt" được sao chép - điều này cũng bất ngờ chuyển quyền sở hữu.
Nó không được dùng trong C ++ 11 và bị xóa trong C ++ 17 , vì vậy bạn không nên sử dụng nó.
std::auto_ptr<MyObject> p1 (new MyObject());
std::auto_ptr<MyObject> p2 = p1; // Copy and transfer ownership.
// p1 gets set to empty!
p2->DoSomething(); // Works.
p1->DoSomething(); // Oh oh. Hopefully raises some NULL pointer exception.
TRẢ LỜI
Một con trỏ thông minh là một lớp bao bọc một con trỏ C ++ 'thô' (hoặc 'trần'), để quản lý thời gian tồn tại của đối tượng được trỏ tới. Không có loại con trỏ thông minh duy nhất, nhưng tất cả chúng đều cố gắng trừu tượng một con trỏ thô theo cách thực tế.
Con trỏ thông minh nên được ưu tiên hơn con trỏ thô. Nếu bạn cảm thấy cần sử dụng con trỏ (trước tiên hãy xem xét nếu bạn thực sự làm như vậy), thông thường bạn sẽ muốn sử dụng một con trỏ thông minh vì điều này có thể làm giảm bớt nhiều vấn đề với con trỏ thô, chủ yếu là quên xóa đối tượng và rò rỉ bộ nhớ.
Với con trỏ thô, lập trình viên phải tiêu diệt rõ ràng đối tượng khi nó không còn hữu ích.
// Need to create the object to achieve some goal
MyObject* ptr = new MyObject();
ptr->DoSomething(); // Use the object in some way
delete ptr; // Destroy the object. Done with it.
// Wait, what if DoSomething() raises an exception...?
Một con trỏ thông minh bằng cách so sánh xác định một chính sách khi đối tượng bị phá hủy. Bạn vẫn phải tạo đối tượng, nhưng bạn không còn phải lo lắng về việc phá hủy nó.
SomeSmartPtr<MyObject> ptr(new MyObject());
ptr->DoSomething(); // Use the object in some way.
// Destruction of the object happens, depending
// on the policy the smart pointer class uses.
// Destruction would happen even if DoSomething()
// raises an exception
Chính sách đơn giản nhất được sử dụng liên quan đến phạm vi của đối tượng trình bao bọc con trỏ thông minh, chẳng hạn như được thực hiện bởi boost::scoped_ptr
hoặc std::unique_ptr
.
void f()
{
{
std::unique_ptr<MyObject> ptr(new MyObject());
ptr->DoSomethingUseful();
} // ptr goes out of scope --
// the MyObject is automatically destroyed.
// ptr->Oops(); // Compile error: "ptr" not defined
// since it is no longer in scope.
}
Lưu ý rằng các std::unique_ptr
trường hợp không thể được sao chép. Điều này ngăn con trỏ bị xóa nhiều lần (không chính xác). Tuy nhiên, bạn có thể chuyển các tham chiếu đến nó xung quanh cho các chức năng khác mà bạn gọi.
std::unique_ptr
s rất hữu ích khi bạn muốn gắn thời gian tồn tại của đối tượng với một khối mã cụ thể hoặc nếu bạn nhúng nó dưới dạng dữ liệu thành viên bên trong một đối tượng khác, thời gian tồn tại của đối tượng đó. Đối tượng tồn tại cho đến khi khối mã chứa được thoát ra hoặc cho đến khi chính đối tượng chứa bị phá hủy.
Một chính sách con trỏ thông minh phức tạp hơn liên quan đến việc tham chiếu đếm con trỏ. Điều này không cho phép con trỏ được sao chép. Khi "tham chiếu" cuối cùng đến đối tượng bị hủy, đối tượng sẽ bị xóa. Chính sách này được thực hiện bởi boost::shared_ptr
và std::shared_ptr
.
void f()
{
typedef std::shared_ptr<MyObject> MyObjectPtr; // nice short alias
MyObjectPtr p1; // Empty
{
MyObjectPtr p2(new MyObject());
// There is now one "reference" to the created object
p1 = p2; // Copy the pointer.
// There are now two references to the object.
} // p2 is destroyed, leaving one reference to the object.
} // p1 is destroyed, leaving a reference count of zero.
// The object is deleted.
Con trỏ đếm tham chiếu rất hữu ích khi thời gian tồn tại của đối tượng của bạn phức tạp hơn nhiều và không được gắn trực tiếp vào một phần mã cụ thể hoặc đối tượng khác.
Có một nhược điểm đối với con trỏ đếm tham chiếu - khả năng tạo tham chiếu lơ lửng:
// Create the smart pointer on the heap
MyObjectPtr* pp = new MyObjectPtr(new MyObject())
// Hmm, we forgot to destroy the smart pointer,
// because of that, the object is never destroyed!
Một khả năng khác là tạo tham chiếu vòng tròn:
struct Owner {
std::shared_ptr<Owner> other;
};
std::shared_ptr<Owner> p1 (new Owner());
std::shared_ptr<Owner> p2 (new Owner());
p1->other = p2; // p1 references p2
p2->other = p1; // p2 references p1
// Oops, the reference count of of p1 and p2 never goes to zero!
// The objects are never destroyed!
Để khắc phục sự cố này, cả Boost và C ++ 11 đều đã xác định a weak_ptr
để xác định tham chiếu yếu (không đếm được) đến a shared_ptr
.
std::auto_ptr<MyObject> p1 (new MyObject());
thay vì std::auto_ptr<MyObject> p1 (new Owner());
?
const std::auto_ptr
an toàn để sử dụng, nếu bạn bị mắc kẹt với C ++ 03. Tôi đã sử dụng nó cho mẫu pimpl khá nhiều cho đến khi tôi có quyền truy cập vào C ++ 11.
Đây là một câu trả lời đơn giản cho những ngày này của C ++ hiện đại (C ++ 11 trở lên):
std::unique_ptr
khi bạn không có ý định giữ nhiều tài liệu tham khảo cho cùng một đối tượng. Ví dụ: sử dụng nó cho một con trỏ tới bộ nhớ được cấp phát khi nhập một số phạm vi và được phân bổ lại khi thoát khỏi phạm vi.std::shared_ptr
khi bạn muốn tham chiếu đến đối tượng của mình từ nhiều nơi - và không muốn đối tượng của mình bị phân bổ cho đến khi tất cả các tham chiếu này tự biến mất.std::weak_ptr
khi bạn muốn tham chiếu đến đối tượng của mình từ nhiều nơi - đối với những tham chiếu mà bạn có thể bỏ qua và phân bổ (vì vậy họ sẽ chỉ lưu ý đối tượng đã biến mất khi bạn cố gắng hủy đăng ký).boost::
con trỏ thông minh hoặc std::auto_ptr
ngoại trừ trong các trường hợp đặc biệt mà bạn có thể đọc lên nếu bạn phải.T*
là std::unique_ptr<T>
những gì std::weak_ptr<T>
làstd::shared_ptr<T>
Con trỏ thông minh là một loại giống như con trỏ với một số chức năng bổ sung, ví dụ như giải quyết bộ nhớ tự động, đếm tham chiếu, v.v.
Giới thiệu nhỏ có sẵn trên trang Con trỏ thông minh - Cái gì, tại sao, cái nào? .
Một trong những loại con trỏ thông minh đơn giản là std::auto_ptr
(chương 20.4.5 của tiêu chuẩn C ++), cho phép tự động phân bổ bộ nhớ khi nó nằm ngoài phạm vi và mạnh hơn so với sử dụng con trỏ đơn giản khi ném ngoại lệ, mặc dù kém linh hoạt hơn.
Một loại tiện lợi khác là boost::shared_ptr
thực hiện đếm tham chiếu và tự động giải phóng bộ nhớ khi không còn tham chiếu đến đối tượng. Điều này giúp tránh rò rỉ bộ nhớ và dễ sử dụng để thực hiện RAII .
Chủ đề được trình bày chuyên sâu trong cuốn sách "Các mẫu C ++: Hướng dẫn hoàn chỉnh" của David Vandevoorde, Nicolai M. Josuttis , chương 20. Con trỏ thông minh. Một số chủ đề được bảo hiểm:
std::auto_ptr
không được chấp nhận và không được khuyến khích vì bạn có thể vô tình chuyển quyền sở hữu. - C ++ 11 loại bỏ sự cần thiết của Boost, sử dụng: std::unique_ptr
, std::shared_ptr
vàstd::weak_ptr
Các định nghĩa được cung cấp bởi Chris, Sergdev và Llyod là chính xác. Tôi thích một định nghĩa đơn giản hơn, chỉ để giữ cho cuộc sống của tôi đơn giản: Một con trỏ thông minh chỉ đơn giản là một lớp làm quá tải các toán tử ->
và *
toán tử. Điều đó có nghĩa là đối tượng của bạn trông giống như một con trỏ nhưng bạn có thể làm cho nó hoạt động tốt hơn, bao gồm đếm tham chiếu, phá hủy tự động, v.v.
shared_ptr
và auto_ptr
là đủ trong hầu hết các trường hợp, nhưng đi kèm với tập hợp các đặc điểm nhỏ của riêng chúng.
Một con trỏ thông minh giống như một con trỏ (gõ) thông thường, như "char *", ngoại trừ khi chính con trỏ đi ra khỏi phạm vi thì những gì nó trỏ đến cũng bị xóa. Bạn có thể sử dụng nó giống như một con trỏ thông thường, bằng cách sử dụng "->", nhưng không phải nếu bạn cần một con trỏ thực sự cho dữ liệu. Vì thế, bạn có thể sử dụng "& * ptr".
Nó rất hữu ích cho:
Các đối tượng phải được phân bổ mới, nhưng bạn muốn có cùng thời gian tồn tại với thứ gì đó trên ngăn xếp đó. Nếu đối tượng được gán cho một con trỏ thông minh, thì chúng sẽ bị xóa khi chương trình thoát khỏi chức năng / khối đó.
Thành viên dữ liệu của các lớp, do đó, khi đối tượng bị xóa, tất cả dữ liệu thuộc sở hữu cũng bị xóa, không có bất kỳ mã đặc biệt nào trong hàm hủy (bạn sẽ cần chắc chắn rằng hàm hủy là ảo, điều này hầu như luôn luôn là một việc nên làm) .
Bạn có thể không muốn sử dụng một con trỏ thông minh khi:
Xem thêm:
Hầu hết các loại con trỏ thông minh xử lý việc xử lý đối tượng con trỏ tới bạn. Nó rất tiện dụng vì bạn không phải suy nghĩ về việc vứt bỏ đồ vật bằng tay nữa.
Các con trỏ thông minh được sử dụng phổ biến nhất là std::tr1::shared_ptr
(hoặc boost::shared_ptr
), và, ít phổ biến hơn , std::auto_ptr
. Tôi khuyên bạn nên sử dụng thường xuyên shared_ptr
.
shared_ptr
rất linh hoạt và xử lý nhiều tình huống xử lý khác nhau, bao gồm cả các trường hợp các đối tượng cần được "vượt qua ranh giới DLL" (trường hợp ác mộng phổ biến nếu các libc
s khác nhau được sử dụng giữa mã của bạn và DLL).
Một con trỏ thông minh là một đối tượng hoạt động giống như một con trỏ, nhưng cũng cung cấp kiểm soát về xây dựng, phá hủy, sao chép, di chuyển và hội nghị.
Người ta có thể thực hiện con trỏ thông minh của riêng mình, nhưng nhiều thư viện cũng cung cấp triển khai con trỏ thông minh, mỗi cái có những ưu điểm và nhược điểm khác nhau.
Ví dụ: Boost cung cấp các triển khai con trỏ thông minh sau:
shared_ptr<T>
là một con trỏ để T
sử dụng số tham chiếu để xác định khi nào đối tượng không còn cần thiết.scoped_ptr<T>
là một con trỏ tự động bị xóa khi nó đi ra khỏi phạm vi. Không có nhiệm vụ là có thể.intrusive_ptr<T>
là một con trỏ đếm tham chiếu khác. Nó cung cấp hiệu suất tốt hơn shared_ptr
, nhưng yêu cầu loại T
để cung cấp cơ chế đếm tham chiếu của riêng nó.weak_ptr<T>
là một con trỏ yếu, làm việc kết hợp với shared_ptr
để tránh các tham chiếu tròn.shared_array<T>
là như thế shared_ptr
, nhưng đối với mảng của T
.scoped_array<T>
là như thế scoped_ptr
, nhưng đối với mảng của T
.Đây chỉ là một mô tả tuyến tính của từng loại và có thể được sử dụng theo nhu cầu, để biết thêm chi tiết và ví dụ người ta có thể xem tài liệu về Boost.
Ngoài ra, thư viện chuẩn C ++ cung cấp ba con trỏ thông minh; std::unique_ptr
cho quyền sở hữu duy nhất, std::shared_ptr
cho sở hữu chung và std::weak_ptr
. std::auto_ptr
tồn tại trong C ++ 03 nhưng hiện không dùng nữa.
scoped_ptr
không giống như khai báo cục bộ const unique_ptr
- cũng bị xóa khi thoát khỏi phạm vi.
Đây là Liên kết cho các câu trả lời tương tự: http://sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html
Một con trỏ thông minh là một đối tượng hoạt động, trông và cảm thấy giống như một con trỏ bình thường nhưng cung cấp nhiều chức năng hơn. Trong C ++, các con trỏ thông minh được triển khai như các lớp mẫu đóng gói một con trỏ và ghi đè các toán tử con trỏ chuẩn. Họ có một số lợi thế so với con trỏ thông thường. Chúng được đảm bảo được khởi tạo là con trỏ null hoặc con trỏ tới một đối tượng heap. Cảm ứng thông qua một con trỏ null được kiểm tra. Không cần xóa là cần thiết. Các đối tượng được tự động giải phóng khi con trỏ cuối cùng với chúng đã biến mất. Một vấn đề quan trọng với những con trỏ thông minh này là không giống như các con trỏ thông thường, chúng không tôn trọng sự kế thừa. Con trỏ thông minh là không hấp dẫn cho mã đa hình. Đưa ra dưới đây là một ví dụ cho việc thực hiện các con trỏ thông minh.
Thí dụ:
template <class X>
class smart_pointer
{
public:
smart_pointer(); // makes a null pointer
smart_pointer(const X& x) // makes pointer to copy of x
X& operator *( );
const X& operator*( ) const;
X* operator->() const;
smart_pointer(const smart_pointer <X> &);
const smart_pointer <X> & operator =(const smart_pointer<X>&);
~smart_pointer();
private:
//...
};
Lớp này triển khai một con trỏ thông minh đến một đối tượng thuộc loại X. Bản thân đối tượng nằm trên heap. Đây là cách sử dụng nó:
smart_pointer <employee> p= employee("Harris",1333);
Giống như các toán tử quá tải khác, p sẽ hoạt động như một con trỏ thông thường,
cout<<*p;
p->raise_salary(0.5);
http://en.wikipedia.org/wiki/Smart_pulum
Trong khoa học máy tính, một con trỏ thông minh là một kiểu dữ liệu trừu tượng mô phỏng một con trỏ trong khi cung cấp các tính năng bổ sung, chẳng hạn như thu thập rác tự động hoặc kiểm tra giới hạn. Các tính năng bổ sung này nhằm giảm các lỗi gây ra bởi việc sử dụng sai con trỏ trong khi vẫn giữ được hiệu quả. Con trỏ thông minh thường theo dõi các đối tượng trỏ đến chúng nhằm mục đích quản lý bộ nhớ. Việc sử dụng sai các con trỏ là một nguồn chính của các lỗi: việc phân bổ, phân bổ và tham chiếu liên tục phải được thực hiện bởi một chương trình được viết bằng con trỏ làm cho rất có thể xảy ra rò rỉ bộ nhớ. Con trỏ thông minh cố gắng ngăn chặn rò rỉ bộ nhớ bằng cách tự động phân bổ tài nguyên: khi con trỏ tới một đối tượng (hoặc cuối cùng trong một loạt các con trỏ) bị phá hủy,
Đặt T là một lớp trong hướng dẫn này Con trỏ trong C ++ có thể được chia thành 3 loại:
1) Con trỏ thô :
T a;
T * _ptr = &a;
Họ giữ một địa chỉ bộ nhớ đến một vị trí trong bộ nhớ. Sử dụng thận trọng, vì các chương trình trở nên phức tạp khó theo dõi.
Con trỏ có dữ liệu const hoặc địa chỉ {Đọc ngược}
T a ;
const T * ptr1 = &a ;
T const * ptr1 = &a ;
Con trỏ tới kiểu dữ liệu T là const. Có nghĩa là bạn không thể thay đổi kiểu dữ liệu bằng con trỏ. tức là *ptr1 = 19
; sẽ không làm việc. Nhưng bạn có thể di chuyển con trỏ. tức là ptr1++ , ptr1--
; vv sẽ làm việc. Đọc ngược: con trỏ để gõ T là const
T * const ptr2 ;
Một con trỏ const đến kiểu dữ liệu T. Có nghĩa là bạn không thể di chuyển con trỏ nhưng bạn có thể thay đổi giá trị được trỏ bởi con trỏ. tức là *ptr2 = 19
sẽ làm việc nhưng ptr2++ ; ptr2--
vv sẽ không hoạt động. Đọc ngược: const con trỏ đến một loại T
const T * const ptr3 ;
Một con trỏ const tới kiểu dữ liệu const T. Có nghĩa là bạn không thể di chuyển con trỏ cũng như không thể thay đổi con trỏ kiểu dữ liệu thành con trỏ. I E . ptr3-- ; ptr3++ ; *ptr3 = 19;
sẽ không làm việc
3) Con trỏ thông minh : { #include <memory>
}
Con trỏ dùng chung :
T a ;
//shared_ptr<T> shptr(new T) ; not recommended but works
shared_ptr<T> shptr = make_shared<T>(); // faster + exception safe
std::cout << shptr.use_count() ; // 1 // gives the number of "
things " pointing to it.
T * temp = shptr.get(); // gives a pointer to object
// shared_pointer used like a regular pointer to call member functions
shptr->memFn();
(*shptr).memFn();
//
shptr.reset() ; // frees the object pointed to be the ptr
shptr = nullptr ; // frees the object
shptr = make_shared<T>() ; // frees the original object and points to new object
Được thực hiện bằng cách sử dụng tính tham chiếu để theo dõi có bao nhiêu "vật" trỏ đến đối tượng được trỏ bởi con trỏ. Khi số này về 0, đối tượng sẽ tự động bị xóa, tức là đối tượng bị xóa khi tất cả các share_ptr trỏ đến đối tượng nằm ngoài phạm vi. Điều này thoát khỏi sự đau đầu của việc phải xóa các đối tượng mà bạn đã phân bổ bằng cách sử dụng mới.
Con trỏ yếu: Giúp xử lý tham chiếu theo chu kỳ phát sinh khi sử dụng Con trỏ chung Nếu bạn có hai đối tượng được trỏ bởi hai con trỏ chia sẻ và có một con trỏ chia sẻ nội bộ trỏ đến từng con trỏ được chia sẻ khác thì sẽ có một tham chiếu theo chu kỳ và đối tượng sẽ không bị xóa khi con trỏ chia sẻ đi ra khỏi phạm vi. Để giải quyết vấn đề này, hãy thay đổi thành viên nội bộ từ shared_ptr thành yếu_ptr. Lưu ý: Để truy cập phần tử được trỏ bởi một con trỏ yếu, hãy sử dụng lock (), điều này trả về một yếu_ptr.
T a ;
shared_ptr<T> shr = make_shared<T>() ;
weak_ptr<T> wk = shr ; // initialize a weak_ptr from a shared_ptr
wk.lock()->memFn() ; // use lock to get a shared_ptr
// ^^^ Can lead to exception if the shared ptr has gone out of scope
if(!wk.expired()) wk.lock()->memFn() ;
// Check if shared ptr has gone out of scope before access
Xem: Khi nào std :: yếu_ptr hữu ích?
Con trỏ độc đáo: Con trỏ thông minh có trọng lượng nhẹ với quyền sở hữu độc quyền. Sử dụng khi con trỏ trỏ đến các đối tượng duy nhất mà không chia sẻ các đối tượng giữa các con trỏ.
unique_ptr<T> uptr(new T);
uptr->memFn();
//T * ptr = uptr.release(); // uptr becomes null and object is pointed to by ptr
uptr.reset() ; // deletes the object pointed to by uptr
Để thay đổi đối tượng được trỏ đến bởi ptr duy nhất, hãy sử dụng di chuyển ngữ nghĩa
unique_ptr<T> uptr1(new T);
unique_ptr<T> uptr2(new T);
uptr2 = std::move(uptr1);
// object pointed by uptr2 is deleted and
// object pointed by uptr1 is pointed to by uptr2
// uptr1 becomes null
Tài liệu tham khảo: Về cơ bản chúng có thể là mặc dù là con trỏ const, tức là một con trỏ là const và không thể di chuyển với cú pháp tốt hơn.
Xem: Sự khác biệt giữa biến con trỏ và biến tham chiếu trong C ++ là gì?
r-value reference : reference to a temporary object
l-value reference : reference to an object whose address can be obtained
const reference : reference to a data type which is const and cannot be modified
Tham khảo: https://www.youtube.com/channel/UCEOGtxYTB6vo6MQ-WQ9W_nQ Cảm ơn Andre vì đã chỉ ra câu hỏi này.
Một con trỏ thông minh là một lớp, một bao bọc của một con trỏ bình thường. Không giống như con trỏ thông thường, vòng đời của điểm thông minh dựa trên số tham chiếu (thời gian đối tượng con trỏ thông minh được chỉ định). Vì vậy, bất cứ khi nào một con trỏ thông minh được gán cho một con trỏ khác, số tham chiếu nội bộ cộng với cộng. Và bất cứ khi nào đối tượng đi ra khỏi phạm vi, số tham chiếu trừ đi.
Con trỏ tự động, mặc dù trông tương tự, hoàn toàn khác với con trỏ thông minh. Đây là một lớp thuận tiện để phân bổ tài nguyên bất cứ khi nào một đối tượng con trỏ tự động đi ra khỏi phạm vi biến. Ở một mức độ nào đó, nó làm cho một con trỏ (bộ nhớ được cấp phát động) hoạt động tương tự như một biến ngăn xếp (được phân bổ tĩnh trong thời gian biên dịch).
Con trỏ thông minh là những nơi bạn không phải lo lắng về Phân bổ bộ nhớ, chia sẻ tài nguyên và chuyển giao.
Bạn rất có thể sử dụng các con trỏ này theo cách tương tự như bất kỳ phân bổ nào hoạt động trong Java. Trong java Garbage Collector thực hiện thủ thuật, trong khi trong Smart Pointers, thủ thuật được thực hiện bởi Dest phá.
Các câu trả lời hiện có là tốt nhưng không bao gồm những gì cần làm khi một con trỏ thông minh không phải là câu trả lời (đầy đủ) cho vấn đề bạn đang cố gắng giải quyết.
Trong số những điều khác (được giải thích tốt trong các câu trả lời khác) bằng cách sử dụng một con trỏ thông minh là một giải pháp khả thi cho Làm thế nào để chúng ta sử dụng một lớp trừu tượng như một kiểu trả về hàm? đã được đánh dấu là một bản sao của câu hỏi này. Tuy nhiên, câu hỏi đầu tiên để hỏi liệu có muốn chỉ định một lớp cơ sở trừu tượng (hoặc trên thực tế là bất kỳ) làm kiểu trả về trong C ++ là "bạn thực sự có ý gì?". Có một cuộc thảo luận tốt (với các tài liệu tham khảo thêm) về lập trình hướng đối tượng thành ngữ trong C ++ (và cách này khác với các ngôn ngữ khác) trong tài liệu của thư viện thùng chứa con trỏ boost. Tóm lại, trong C ++, bạn phải nghĩ về quyền sở hữu. Những con trỏ thông minh nào giúp bạn, nhưng không phải là giải pháp duy nhất hoặc luôn luôn là một giải pháp hoàn chỉnh (chúng không cung cấp cho bạn bản sao đa hình) và không phải lúc nào cũng là một giải pháp bạn muốn đưa ra trong giao diện của mình (và trả về chức năng nghe có vẻ khủng khiếp rất giống một giao diện). Nó có thể là đủ để trả lại một tài liệu tham khảo, ví dụ. Nhưng trong tất cả các trường hợp này (con trỏ thông minh, thùng chứa con trỏ hoặc đơn giản là trả về một tham chiếu), bạn đã thay đổi trả về từ một giá trị thành một dạng tham chiếu nào đó hoặc Boost.TypeErasure. Nếu bạn thực sự cần sao chép, bạn có thể cần thêm "thành ngữ" soạn sẵn hoặc vượt ra ngoài OOP thành ngữ (hoặc nói cách khác) trong C ++ sang đa hình chung hơn bằng các thư viện như Adobe Poly .