|
2864 | 2864 | \end{codeblock} |
2865 | 2865 | \end{example} |
2866 | 2866 |
|
| 2867 | +\rSec2[class.free]{Free store}% |
| 2868 | +\indextext{free store}% |
| 2869 | + |
| 2870 | +\pnum |
| 2871 | +\indextext{\idxcode{new}!type of} |
| 2872 | +Any allocation function for a class |
| 2873 | +\tcode{T} |
| 2874 | +is a static member (even if not explicitly declared |
| 2875 | +\keyword{static}). |
| 2876 | + |
| 2877 | +\pnum |
| 2878 | +\begin{example} |
| 2879 | +\begin{codeblock} |
| 2880 | +class Arena; |
| 2881 | +struct B { |
| 2882 | + void* operator new(std::size_t, Arena*); |
| 2883 | +}; |
| 2884 | +struct D1 : B { |
| 2885 | +}; |
| 2886 | + |
| 2887 | +Arena* ap; |
| 2888 | +void foo(int i) { |
| 2889 | + new (ap) D1; // calls \tcode{B::operator new(std::size_t, Arena*)} |
| 2890 | + new D1[i]; // calls \tcode{::operator new[](std::size_t)} |
| 2891 | + new D1; // error: \tcode{::operator new(std::size_t)} hidden |
| 2892 | +} |
| 2893 | +\end{codeblock} |
| 2894 | +\end{example} |
| 2895 | + |
| 2896 | +\pnum |
| 2897 | +\indextext{\idxcode{delete}!type of}% |
| 2898 | +Any deallocation function for a class |
| 2899 | +\tcode{X} |
| 2900 | +is a static member (even if not explicitly declared |
| 2901 | +\keyword{static}). |
| 2902 | +\begin{example} |
| 2903 | +\begin{codeblock} |
| 2904 | +class X { |
| 2905 | + void operator delete(void*); |
| 2906 | + void operator delete[](void*, std::size_t); |
| 2907 | +}; |
| 2908 | + |
| 2909 | +class Y { |
| 2910 | + void operator delete(void*, std::size_t); |
| 2911 | + void operator delete[](void*); |
| 2912 | +}; |
| 2913 | +\end{codeblock} |
| 2914 | +\end{example} |
| 2915 | + |
| 2916 | +\pnum |
| 2917 | +Since member allocation and deallocation functions are |
| 2918 | +\keyword{static} |
| 2919 | +they cannot be virtual. |
| 2920 | +\begin{note} |
| 2921 | +However, when the |
| 2922 | +\grammarterm{cast-expression} |
| 2923 | +of a |
| 2924 | +\grammarterm{delete-expression} |
| 2925 | +refers to an object of class type with a virtual destructor, |
| 2926 | +because the deallocation function is chosen by the destructor |
| 2927 | +of the dynamic type of the object, the effect is the same in that case. |
| 2928 | +For example, |
| 2929 | +\begin{codeblock} |
| 2930 | +struct B { |
| 2931 | + virtual ~B(); |
| 2932 | + void operator delete(void*, std::size_t); |
| 2933 | +}; |
| 2934 | + |
| 2935 | +struct D : B { |
| 2936 | + void operator delete(void*); |
| 2937 | +}; |
| 2938 | + |
| 2939 | +struct E : B { |
| 2940 | + void log_deletion(); |
| 2941 | + void operator delete(E *p, std::destroying_delete_t) { |
| 2942 | + p->log_deletion(); |
| 2943 | + p->~E(); |
| 2944 | + ::operator delete(p); |
| 2945 | + } |
| 2946 | +}; |
| 2947 | + |
| 2948 | +void f() { |
| 2949 | + B* bp = new D; |
| 2950 | + delete bp; // 1: uses \tcode{D::operator delete(void*)} |
| 2951 | + bp = new E; |
| 2952 | + delete bp; // 2: uses \tcode{E::operator delete(E*, std::destroying_delete_t)} |
| 2953 | +} |
| 2954 | +\end{codeblock} |
| 2955 | +Here, storage for the object of class |
| 2956 | +\tcode{D} |
| 2957 | +is deallocated by |
| 2958 | +\tcode{D::operator delete()}, |
| 2959 | +and |
| 2960 | +the object of class \tcode{E} is destroyed |
| 2961 | +and its storage is deallocated |
| 2962 | +by \tcode{E::operator delete()}, |
| 2963 | +due to the virtual destructor. |
| 2964 | +\end{note} |
| 2965 | +\begin{note} |
| 2966 | +Virtual destructors have no effect on the deallocation function actually |
| 2967 | +called when the |
| 2968 | +\grammarterm{cast-expression} |
| 2969 | +of a |
| 2970 | +\grammarterm{delete-expression} |
| 2971 | +refers to an array of objects of class type. |
| 2972 | +For example, |
| 2973 | +\begin{codeblock} |
| 2974 | +struct B { |
| 2975 | + virtual ~B(); |
| 2976 | + void operator delete[](void*, std::size_t); |
| 2977 | +}; |
| 2978 | + |
| 2979 | +struct D : B { |
| 2980 | + void operator delete[](void*, std::size_t); |
| 2981 | +}; |
| 2982 | + |
| 2983 | +void f(int i) { |
| 2984 | + D* dp = new D[i]; |
| 2985 | + delete [] dp; // uses \tcode{D::operator delete[](void*, std::size_t)} |
| 2986 | + B* bp = new D[i]; |
| 2987 | + delete[] bp; // undefined behavior |
| 2988 | +} |
| 2989 | +\end{codeblock} |
| 2990 | +\end{note} |
| 2991 | + |
| 2992 | +\pnum |
| 2993 | +Access to the deallocation function is checked statically, |
| 2994 | +even if a different one is actually executed. |
| 2995 | +\begin{example} |
| 2996 | +For the call on line ``// 1'' above, |
| 2997 | +if |
| 2998 | +\tcode{B::operator delete()} |
| 2999 | +had been private, the delete expression would have been ill-formed. |
| 3000 | +\end{example} |
| 3001 | + |
| 3002 | +\pnum |
| 3003 | +\begin{note} |
| 3004 | +If a deallocation function has no explicit \grammarterm{noexcept-specifier}, it |
| 3005 | +has a non-throwing exception specification\iref{except.spec}. |
| 3006 | +\end{note} |
| 3007 | + |
2867 | 3008 | \rSec2[class.nest]{Nested class declarations}% |
2868 | 3009 | \indextext{definition!nested class}% |
2869 | 3010 |
|
|
6634 | 6775 | \end{codeblock} |
6635 | 6776 | \end{example} |
6636 | 6777 |
|
6637 | | -\rSec1[class.free]{Free store}% |
6638 | | -\indextext{free store}% |
6639 | | - |
6640 | | -\pnum |
6641 | | -\indextext{\idxcode{new}!type of} |
6642 | | -Any allocation function for a class |
6643 | | -\tcode{T} |
6644 | | -is a static member (even if not explicitly declared |
6645 | | -\keyword{static}). |
6646 | | - |
6647 | | -\pnum |
6648 | | -\begin{example} |
6649 | | -\begin{codeblock} |
6650 | | -class Arena; |
6651 | | -struct B { |
6652 | | - void* operator new(std::size_t, Arena*); |
6653 | | -}; |
6654 | | -struct D1 : B { |
6655 | | -}; |
6656 | | - |
6657 | | -Arena* ap; |
6658 | | -void foo(int i) { |
6659 | | - new (ap) D1; // calls \tcode{B::operator new(std::size_t, Arena*)} |
6660 | | - new D1[i]; // calls \tcode{::operator new[](std::size_t)} |
6661 | | - new D1; // error: \tcode{::operator new(std::size_t)} hidden |
6662 | | -} |
6663 | | -\end{codeblock} |
6664 | | -\end{example} |
6665 | | - |
6666 | | -\pnum |
6667 | | -\indextext{\idxcode{delete}!type of}% |
6668 | | -Any deallocation function for a class |
6669 | | -\tcode{X} |
6670 | | -is a static member (even if not explicitly declared |
6671 | | -\keyword{static}). |
6672 | | -\begin{example} |
6673 | | -\begin{codeblock} |
6674 | | -class X { |
6675 | | - void operator delete(void*); |
6676 | | - void operator delete[](void*, std::size_t); |
6677 | | -}; |
6678 | | - |
6679 | | -class Y { |
6680 | | - void operator delete(void*, std::size_t); |
6681 | | - void operator delete[](void*); |
6682 | | -}; |
6683 | | -\end{codeblock} |
6684 | | -\end{example} |
6685 | | - |
6686 | | -\pnum |
6687 | | -Since member allocation and deallocation functions are |
6688 | | -\keyword{static} |
6689 | | -they cannot be virtual. |
6690 | | -\begin{note} |
6691 | | -However, when the |
6692 | | -\grammarterm{cast-expression} |
6693 | | -of a |
6694 | | -\grammarterm{delete-expression} |
6695 | | -refers to an object of class type with a virtual destructor, |
6696 | | -because the deallocation function is chosen by the destructor |
6697 | | -of the dynamic type of the object, the effect is the same in that case. |
6698 | | -For example, |
6699 | | -\begin{codeblock} |
6700 | | -struct B { |
6701 | | - virtual ~B(); |
6702 | | - void operator delete(void*, std::size_t); |
6703 | | -}; |
6704 | | - |
6705 | | -struct D : B { |
6706 | | - void operator delete(void*); |
6707 | | -}; |
6708 | | - |
6709 | | -struct E : B { |
6710 | | - void log_deletion(); |
6711 | | - void operator delete(E *p, std::destroying_delete_t) { |
6712 | | - p->log_deletion(); |
6713 | | - p->~E(); |
6714 | | - ::operator delete(p); |
6715 | | - } |
6716 | | -}; |
6717 | | - |
6718 | | -void f() { |
6719 | | - B* bp = new D; |
6720 | | - delete bp; // 1: uses \tcode{D::operator delete(void*)} |
6721 | | - bp = new E; |
6722 | | - delete bp; // 2: uses \tcode{E::operator delete(E*, std::destroying_delete_t)} |
6723 | | -} |
6724 | | -\end{codeblock} |
6725 | | -Here, storage for the object of class |
6726 | | -\tcode{D} |
6727 | | -is deallocated by |
6728 | | -\tcode{D::operator delete()}, |
6729 | | -and |
6730 | | -the object of class \tcode{E} is destroyed |
6731 | | -and its storage is deallocated |
6732 | | -by \tcode{E::operator delete()}, |
6733 | | -due to the virtual destructor. |
6734 | | -\end{note} |
6735 | | -\begin{note} |
6736 | | -Virtual destructors have no effect on the deallocation function actually |
6737 | | -called when the |
6738 | | -\grammarterm{cast-expression} |
6739 | | -of a |
6740 | | -\grammarterm{delete-expression} |
6741 | | -refers to an array of objects of class type. |
6742 | | -For example, |
6743 | | -\begin{codeblock} |
6744 | | -struct B { |
6745 | | - virtual ~B(); |
6746 | | - void operator delete[](void*, std::size_t); |
6747 | | -}; |
6748 | | - |
6749 | | -struct D : B { |
6750 | | - void operator delete[](void*, std::size_t); |
6751 | | -}; |
6752 | | - |
6753 | | -void f(int i) { |
6754 | | - D* dp = new D[i]; |
6755 | | - delete [] dp; // uses \tcode{D::operator delete[](void*, std::size_t)} |
6756 | | - B* bp = new D[i]; |
6757 | | - delete[] bp; // undefined behavior |
6758 | | -} |
6759 | | -\end{codeblock} |
6760 | | -\end{note} |
6761 | | - |
6762 | | -\pnum |
6763 | | -Access to the deallocation function is checked statically, |
6764 | | -even if a different one is actually executed. |
6765 | | -\begin{example} |
6766 | | -For the call on line ``// 1'' above, |
6767 | | -if |
6768 | | -\tcode{B::operator delete()} |
6769 | | -had been private, the delete expression would have been ill-formed. |
6770 | | -\end{example} |
6771 | | - |
6772 | | -\pnum |
6773 | | -\begin{note} |
6774 | | -If a deallocation function has no explicit \grammarterm{noexcept-specifier}, it |
6775 | | -has a non-throwing exception specification\iref{except.spec}. |
6776 | | -\end{note} |
6777 | | - |
6778 | 6778 | \indextext{class|)} |
0 commit comments