了解std::set.insert
& std::vector
行为。
请考虑以下情况:
A.H
class A {
uint id;
vector<double> values;
operator<(const A& argA) const;
}
A.cpp
A::A(uint argId, vector<double> argValues) {
this->id = argId;
this->values = argValues;
}
A::operator<(const A& argA) const {
// it's guaranteed that there's always at least one element in the vector
return this->values[0] < argA.values[0];
}
B.cpp
std::set<A> mySet;
for (uint i = 0; i < (uint) 10; i++)
{
vector<double> tempVector(3);
for (uint j = 0; j < (uint) 3; j++) {
tempVector[j] = j;
}
myset.insert(A(i + 1, tempVector));
}
根据我的理解,tempElement
拥有深度复制的向量(值),因为vector
在其构造函数中通过值传递并分配。因此,循环遍历i不应该将添加的元素分解为我的集合。但是插入*tempElement
个中断 - SIGSEV。在我的逻辑中,这应该工作......每一个帮助都赞赏!
编辑:代码在插入过程中崩溃(第二个元素); set调用LT运算符,尝试访问传递参数的向量 - 但不能。在创建A之前,我传递了id和向量,我检查传递的向量是否包含正确的元素。
答案 0 :(得分:1)
对于一个小向量,它应该没关系,但是如果你有一个大数组并且继续复制它会很昂贵,那么你的A
应该包含一些浅拷贝的指针。有几种选择:
boost::shared_array<double>
boost::shared_ptr<vector<double> >
boost::shared_ptr<double>
但是在构造中传入了数组删除器。请注意,使用shared_array
或shared_ptr
,您将无法提取大小(元素数量),因此您必须单独存储它。
答案 1 :(得分:0)
我认为问题不在于此代码中。但是我注意到你有一个矢量tempVector,但你将值赋给tempComponents。我看不到tempComponents声明,但我的猜测是它的大小不同。
答案 2 :(得分:0)
不,没有理由在此插入myset导致崩溃。问题必须在其他地方。如果你没有使用默认版本,也许在A的副本中。
但是你的代码泄漏了内存。当您插入集*tempElement
时,会将new
复制到集合中,然后不再使用您使用A tempElement(i+1,tempVector);
分配的原始内容,但永远不会删除。相反,您可以只执行myset.insert(A(i+1,tempVector))
,以便在将对象复制到集合中后,它会被正确销毁。或者在这种情况下可能更好,你可以将它构造为临时传递给insert:myset.emplace(i+1,tempVector);
,在这种情况下,对象将被移动而不是复制,从而减少了开销。或者您可以构建对象以避免移动:tempComponents[j] = j;
此外,我假设您tempVector[j] = j
表示std::iota(begin(tempVector),end(tempVector),0)
。您可以用vector<double> tempVector(3) = {0.0,1.0,2.0}
std::set<A> mySet;
for (uint i = 0; i < (uint) 10; i++)
{
myset.emplace(i+1,tempVector);
}
替换该循环。 编辑:或者您可以使用新的初始化程序语法此外,由于每次只使用循环外的向量,向量是相同的:
emplace
C ++ 03编译器不支持iota
或新的初始化语法,而double tempVector_init[] = {0.0,1.0,2.0};
vector<double> tempVector(tempVector_init,tempVector_init+3);
std::set<A> mySet;
for (uint i = 0; i < (uint) 10; i++)
{
myset.insert(A(i+1,tempVector));
}
将是它们的编译器扩展(它来自原始的SGI STL,所以有些人可能会这样做。对于那些你仍然会使用insert并使用for循环初始化tempVector或使用数组:
{{1}}
答案 3 :(得分:0)
工作代码有很多变化 - 但我没有看到你所描述的问题。
#include <set>
#include <vector>
using namespace std;
typedef unsigned int uint;
class A {
public:
A(uint argId, vector<double> argValues)
{
this->id = argId;
this->values = argValues;
}
bool operator < ( A const& a ) const
{
return a.id < id;
}
uint id;
vector<double> values;
};
int _tmain(int argc, _TCHAR* argv[])
{
std::set<A> mySet;
for (uint i = 0; i < (uint) 10; i++)
{
vector<double> tempVector(3);
for (uint j = 0; j < (uint) 3; j++) {
tempVector[j] = j;
}
std::unique_ptr<A> tempElement(new A(i + 1, tempVector));
mySet.insert(*tempElement);
}
return 0;
}