在什么情况下使用is_nothrow_constructible变得很重要?为什么它很重要?它的用途是什么?
is_nothrow_constructible
j1dl9f461#
假设你正在实现new,如果构造函数不能抛出,那么你可以简单地分配内存并执行placement new。现在如果构造函数可以抛出,你必须添加一个保护,以释放分配的内存,以防异常发生在构造函数中。如果它是一个new[],它分配了一个某种类型的数组,那么如果数组的元素可以在构造时抛出,那么你应该确保守卫知道到底有多少元素被构造,并在异常时销毁它们,除了释放内存。好吧,通常不需要实现new,但是定制的vector类或其他一些你想要的容器,手动分配内存并在各种操作中使用placement new呢?在这种情况下,你可以使用trait来优化构造函数不抛出的情况。
new
new[]
vector
wz3gfoph2#
您将看到它的主要用途是计算不同的函数是否应该是noexcept。例如,std::pair的构造函数可能如下所示:
noexcept
std::pair
template<typename T1, typename T2> template<typename T, typename U> pair<T1, T2>::pair(T&& x, U&& y) noexcept(std::is_nothrow_constructible_v<T1, T&&> && std::is_nothrow_constructible_v<T2, U&&>) : first(std::forward<T>(x)), second(std::forward<U>(y)) {}
这意味着noexcept-ness可以更好地传播出去,有助于其他一些优化。std::move_if_noexcept是一种完全不同的行为,它使用std::is_nothrow_constructible<T, T&&>来决定是否应该从其中移动或复制某些内容。它用于维护“强异常保证”。例如,当调整向量大小时,如果它不能抛出,它将把项移动到新的内存中,否则它将复制(如果复制抛出,原始内容仍然有效)。
std::move_if_noexcept
std::is_nothrow_constructible<T, T&&>
2条答案
按热度按时间j1dl9f461#
假设你正在实现
new
,如果构造函数不能抛出,那么你可以简单地分配内存并执行placement new。现在如果构造函数可以抛出,你必须添加一个保护,以释放分配的内存,以防异常发生在构造函数中。
如果它是一个
new[]
,它分配了一个某种类型的数组,那么如果数组的元素可以在构造时抛出,那么你应该确保守卫知道到底有多少元素被构造,并在异常时销毁它们,除了释放内存。好吧,通常不需要实现
new
,但是定制的vector
类或其他一些你想要的容器,手动分配内存并在各种操作中使用placement new呢?在这种情况下,你可以使用trait来优化构造函数不抛出的情况。
wz3gfoph2#
您将看到它的主要用途是计算不同的函数是否应该是
noexcept
。例如,
std::pair
的构造函数可能如下所示:这意味着
noexcept
-ness可以更好地传播出去,有助于其他一些优化。std::move_if_noexcept
是一种完全不同的行为,它使用std::is_nothrow_constructible<T, T&&>
来决定是否应该从其中移动或复制某些内容。它用于维护“强异常保证”。例如,当调整向量大小时,如果它不能抛出,它将把项移动到新的内存中,否则它将复制(如果复制抛出,原始内容仍然有效)。