《"Overload"》杂志中的奇怪收货

Strange Receipe from the "Overload" magazine

本文关键字:杂志 "Overload"      更新时间:2023-10-16

我在2013年2月的"Overload"杂志上看到了这段代码。我理解所提供的代码,但我完全错过了它的目的,既不是与std:: auto_ptr的类比,也不是节省alloc/dealloc周期。如果有人能用他自己的话重新解释一下这个"配方"。描述如下:

Recipe #2——带有"move"语义的容器很奇怪,但是每本好的食谱都应该至少包含一个奇怪的食谱,开始吧。在高性能代码中,有场景中,您需要有一个容器来存储复杂的对象(这些对象包括已分配的存储空间等),但是那些对象只被移动,不被复制。提供副本这类对象的构造函数可能是困难的(例如,如果这样的对象包括一个文件句柄)或对性能不利原因(如果这样的对象包含已分配的内存,复制其中会很贵)。一种常见的处理方法是使用一些一种引用计数指针(或类似的东西)auto_ptr<>);这是一个可行的选择,但它有相关的成本额外的分配/释放,在真正的高性能代码,这可能是个问题。在这种情况下,方法类似于下面的方法可以帮助你改写一句谚语,你可以这么说奇怪的时间需要奇怪的度量)—参见清单2。

//class X is our complicated class
class StackOfX {
    // stack is just one example; any other type of
    // container (including maps, sets, lists, etc.)
    // can be written in a similar manner
    struct ShadowX { char data[ sizeof(X) ]; };
    typedef vector<ShadowX> ShadowV;
    ShadowV v;
    void push( /* move-in */ X& x ) {
        ShadowX& sx = (ShadowX&)x;
        v.insert( v.end(), sx );
    }
    const X& operator[]( int i ) const {
        return (const X&)v[ i ];
    }
    void pop( /* move-out */ X& x ) {
        ShadowV::iterator it = v.end() - 1;
        ShadowX& sx = (ShadowX&)x;
        sx = *it;
        v.erase( it );
    }
    ~StackOfX() {
        for( ShadowV::iterator it = v.begin();
        it != v.end(); ++it ) {
            X& x = (X&)(*it);
            x.X::~X();
        }
    }
};

这段代码似乎能够复制不支持复制的对象,方法是将它们视为字节序列。

这样做不是一个好主意,但如果要这样做,使用memcpy比愚蠢的重新解释更清楚。

c++ 11引入对move语义的支持。在此之前,c++ 03中有Andrei的Mojo之类的东西(但从未成功过)。在move语义支持下,即使对象不可复制,也可以将其放入容器中。

这在c++ 11中已经完全过时了,c++ 11直接在语言中提供了move语义的语法。

找一本真正好的和最新的书,《权威c++图书指南和列表》

引用那一页:有很多非常糟糕的c++书