我正在尝试使用智能指针,并尝试在我的项目中使用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一起玩。
提前致谢!
答案 0 :(得分:1)
这个问题没什么意义。使用shared_ptr
或unique_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=
,但不承诺不修改原始容器。