unique_ptrs向量的赋值运算符

时间:2012-08-03 02:32:31

标签: c++ operator-overloading smart-pointers stdvector unique-ptr

我正在尝试使用智能指针,并尝试在我的项目中使用unique_ptr交换一些shared_ptr,看看我是否可以获得很少的性能提升。

我有以下代码snippt:

// --- probably can be replaced with with std::copy ...
if (j != sentences.size()) {
    // also gives me an error if I initialize vector with a size.
    std::vector<unique_ptr<StemmedSentence> > newSentences(j);
    int base = 0;
    for (size_t i = 0; i < j; i++) {
        newSentences[base++] = std::move(sentences[i]); // std::move ??
    }
    sentences = newSentences; // std::move, i guess not !?
}

我将一个指针向量复制到一个新的向量中(在本例中是unique_ptr的向量)。使用shared_ptr,这根本不是问题。据我所知,共享指针使用隐式赋值,一切正常。但是对于unique_ptr,我需要重载赋值运算符(转移所有权),这让我很安静。

我创建了这个作业:

ArrayStemmedSnippet& operator=(const ArrayStemmedSnippet& other) {
    if (this != &other) {
        sentences.clear();
        std::vector<unique_ptr<StemmedSentence> >::const_iterator it;
        for (it = other.sentences.begin(); it != other.sentences.end(); ++it) {
            sentences.push_back(std::unique_ptr< StemmedSentence >(*it ? 
                *it : std::unique_ptr< StemmedSentence >())); // --- compiler error
        }
        return (*this);
    }
}

复制指针可以包含“Null”指针。我尝试在for循环中检查这个 并复制指针或空的unique_ptr实例(nullptr)。 那个标有编译器错误的行给了我一个问题,我无法弄清楚正确的语法。另外我想如果我复制一个非空对象,我必须创建一个新指针(克隆)。有人可以给我一个提示吗?

我发现了一篇类似的帖子Handling smart pointers in stl container,Howard Hinnant的回答给了我一些尝试的灵感。但是我不能使用那种语法,我的testmachine上有gcc版本4.4.3。

我不知道我是否会获得更多的表现,就像我说的那样,我进行了实验。据我所知,我的代码中没有所有权问题,因此我认为使用unique_ptr进行测试并跳过shared_ptr(带有所有开销)可能会略微提高性能。我有大约5个使用shared_ptr的对象,所以我试试看。

如果这一切都没有意义,请告诉我是否值得与uniqe_ptr一起玩。

提前致谢!

1 个答案:

答案 0 :(得分:1)

这个问题没什么意义。使用shared_ptrunique_ptr的决定应基于所有权是共享还是唯一。问题是关注强制改变设计的细节,这可能是不想要的。

在原始设计中,多个向量包含shared_ptr并共享其他一些对象的所有权,但在修改后的方法中,因为unique_ptr具有唯一所有权,您将成为被迫复制对象。更改的副作用是多方面的:现在您需要复制对象(成本更高)。因为类型是基础,所以您需要实现clone()方法,以便不切片对象,这也会产生(最小)成本。复制完成后,矢量将不再引用共享对象,因此通过其中一个执行的更改将无法通过其余部分显示,从而更改语义。

此时,我只能开始考虑你是否有 profiled 你的代码,以及应用程序的多少成本是复制共享指针,因为那是不是昂贵的操作。我的感觉是你可能会在错误的树上狂吠,花费时间不必要地在这个过程中打破你的应用程序,用一种更加模糊的方法来做任何事情。

对不起听起来很消极,但我觉得你应该真的想到这一点。 unique_ptr不是shared_ptr的替代,除非shared_ptr从一开始就是错误的解决方案(对象不应该真正被共享),但事实并非如此,因为在你当前程序你复制指向不同容器的指针,从而分享


如果你想要的是压缩矢量,你根本不需要需要副本,甚至编码:

// [untested, but you can build on top of this]
typedef std::vector< std::unique_ptr< StemmedSentence > > vector_t;

vector_t v = ... // build the vector
// compact:
v.erase( std::remove( std::make_move_iterator( v.begin() ),
                      std::make_move_iterator( v.end() ),
                      std::unique_ptr<StemmedSentence>() 
                    ).base(),
         v.end() );

但是不应该常量引用的封闭类型上实现为operator=unique_ptr无法共享所有权,因此如果指针已移动到新容器,则旧容器将清空(这可能适合移动 operator=,但不承诺不修改原始容器。