0

我正在尝试使用智能指针,并尝试在我的项目中将一些 shared_ptr 与 unique_ptr 进行交换,看看我是否能获得一点性能改进。

我有以下代码片段:

// --- 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 的回答给了我尝试的灵感。但我不能使用那种语法,我的测试机上有 gcc 版本 4.4.3。

我不知道我是否会获得更多的性能,就像我说的,我做实验。据我所知,我的代码中没有所有权问题,所以我认为使用 unique_ptr 进行测试并跳过 shared_ptr(及其所有开销)可能会在性能上有所提高。我有大约 5 个使用 shared_ptr 的对象,所以我会试一试。

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

提前致谢!

4

1 回答 1

1

这个问题意义不大。使用shared_ptrunique_ptr应该根据所有权是共享的还是唯一的来决定。问题集中在强制改变可能不想要的设计的细节上。

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

在这一点上,我只能开始思考您是否已经对您的代码进行了概要分析,以及应用程序在复制共享指针方面的成本有多少,因为这不是一项昂贵的操作。我的感觉是,您可能会在错误的树上吠叫,花费不必要的时间并在此过程中破坏您的应用程序,而使用一种更加晦涩的方法是徒劳的。

很抱歉听起来很消极,但我觉得你应该认真考虑一下。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=

于 2012-08-03T03:32:18.587 回答