2012-10-04 236 views
2

最近我读到这样一段代码:这个“新”语法是什么意思?

template <unsigned long size> 
class FooBase 
{ 
    bool m_bValid; 
    char m_data[size]; 
}; 

template <class T> 
class Foo : public FooBase<sizeof(T)> 
{ 
    // it's constructor 
    Foo(){}; 
    Foo(T const & t) {construct(t); m_bValid = (true);} 

    T const * const GetT() const { return reinterpret_cast<T const * const>(m_data); } 
    T * const GetT() { return reinterpret_cast<T * const>(m_data);} 

    // could anyone help me understand this line?? 
    void construct(T const & t) {new (GetT()) T(t);} 
}; 

我已经切片的代码,以确保它并不复杂,主要的问题是关于construct(T const & t)功能。

new (GetT()) T(t);究竟是什么意思?

btw,哪个版本的GetT()被调用?

+0

这是值得注意的是,这个代码是非常脆弱的......如果'm_data'成员没有一个'T'对象对齐适当您的特定CPU /内存架构,那么程序可能会崩溃。对齐/打包是一个实现细节(即没有被标准规定)。特定的编译器通常会提供编译/扩展来控制打包。这个代码可以通过在'm_bValid'之前将'm_data [size]'成员移动到FooBase的前面来解决。 –

+0

@TonyD代码被切片,正如我所说:)实际上它来自“游戏编码完成”2006年版,第3章第5节'optional.h'。感谢编译器问题,当我使用这个类时,我会关注它。 – shengy

+0

您的'Foo <> :: GetT'函数非常危险,因为'reinterpret__cast'! – PiotrNycz

回答

5

new (GetT()) T(t);究竟是什么意思?

这是Placement new,它可以让你把一个对象在内存中的特定位置,这是由Get()返回。

哪个版本的GetT()被调用?

第二个。
只要编译器有选择在const和非const函数之间进行选择,它就会选择非const的版本。
具体来说,在这种情况下,@James在评论中指出:
非const版本被给予优先权,因为调用它的成员函数是非const的。

+1

在这种情况下,它必须选择非常量版本,因为放置新需要写入一个非常量缓冲区。 –

+1

在这种情况下,它是非常量版本,因为调用它的成员函数是非常量的。 –

1

这看起来就像是一个安置新的电话。这里没有分配内存。 new只是返回括号中的地址,并且在虚拟构建的对象上调用构造函数。

+0

您可能想澄清“虚拟构建”的含义。关于调用没有什么“虚拟”,与通过自动存储或普通的'new'运算符实例化的任何其他对象一样,该对象完全为真实构建。 –

2

这就是所谓的“安置新”。

这意味着您在给定的内存缓冲区上创建一个新对象。

new (buffer) T(); //means it will instantiate an object T in the buffer. 

这使您可以拥有内存缓冲区和自定义分配器,而无需从操作系统请求和分配新内存。

阅读: What uses are there for "placement new"?