【问题标题】:What is the difference between new and ::newnew 和 ::new 有什么区别
【发布时间】:2018-08-02 09:04:36
【问题描述】:

boost 等许多库都使用 ::new::delete

来自boost::make_shared的示例

template< class T, class... Args > typename boost::detail::sp_if_not_array< T >::type make_shared( Args && ... args )
{
    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );

    boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );

    void * pv = pd->address();

    ::new( pv ) T( boost::detail::sp_forward<Args>( args )... );
    pd->set_initialized();

    T * pt2 = static_cast< T* >( pv );

    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
    return boost::shared_ptr< T >( pt, pt2 );
}

这是什么意思?为什么要使用::new 而不是新的?

【问题讨论】:

标签: c++


【解决方案1】:

一个类C 可以定义它自己的operator new(例如,这样可以为该类拥有自己的分配策略,和/或为其提供一些Allocator。许多标准containers 模板接受可选的分配器参数,例如 std::vector 的第二个参数;另请参见 std::allocatorthis 示例)。

如果您编码new C,则将使用该运算符(如果存在)。

如果您编码::new C,则使用全局new

您的示例使用全局 placement new

【讨论】:

    【解决方案2】:

    newnew[]deletedelete[](包括放置变体)在class 和在全局范围内都可以覆盖both ,尽管这样做是不明智的。

    当您看到::new 时,您使用的是全局new 运算符。

    【讨论】:

    • 全局放置 new,与其他全局函数不同(谢天谢地),应用程序无法替换。这本质上是对黑暗艺术的防御。
    • 在全局范围内使用时 new 和 ::new 是否相同?
    • @EduardRostomyan:当然!
    • @EduardRostomyan 否:new X 将更喜欢在class X 本身中定义的operator new 函数,或者X 的基类或包含X 的命名空间。 ::new X 将只使用全局 ::operator new 函数。
    【解决方案3】:

    一般来说,只要在 LHS 中使用范围解析 (::) 运算符而没有任何说明符,它指的是全局范围。这里也一样。

    来到运算符new,它可以在本地和外部范围内重载。因此使用全局变量范围解析操作符来访问。

    【讨论】:

      【解决方案4】:

      new 可以被覆盖和替换。因此,简单地声明 new 并不总能得到您想要的 new

      在这种特定情况下,我们正在寻找新的展示位置:

      void * pv = pd->address();
      
      ::new( pv ) T( boost::detail::sp_forward<Args>( args )... );
      

      这是我们试图在位置pv 中构造T 的地方。

      为避免调用new 的覆盖而不是“真实”放置new 的可能性,您必须使用::new( void pointer here ) type( arguments... );。该特定的new 既不能被替换也不能被覆盖。

      【讨论】:

      • 不能吗?实际上,它通常可以 - 大多数 c++ 运行时都提供一个静态库,并且由于 c++ 不会阻止您定义自己的全局运算符 new,因此大多数时候您可以有效地替换内置实现。就 c++ 规范而言,它可能属于“未定义/实现定义”的行为。
      • 最后一段听起来像(通常的void*)placement new 是普通new 的直接替换,只是为了避免使用不同或可替换的operator new,但它们有很大不同行为:Plain new 为您分配内存,但放置 new 需要一些已经有效的内存区域。
      • @ChrisBecke C++ 规范确实对任何用户定义的全局 operator new 替换定义了许多要求,以确保它基本保持正常。如果不遵守这些,是的,你有未定义的行为。
      【解决方案5】:

      普通的 new 操作符是在类范围内实现的,可以被覆盖,而 ::new 是在全局范围内实现的,不能被覆盖。

      【讨论】:

        猜你喜欢
        • 2011-11-22
        • 1970-01-01
        • 2018-06-04
        • 2012-12-29
        • 2017-10-31
        • 2011-04-23
        • 2014-02-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多