|
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