最近我从一家外部公司得到了一段代码,看起来有点奇怪。所以我的问题是:有人能解释下面代码设计的好坏点吗?
有一个
class A
{
double val[2]; // actually within the original class there are:
// an int, two std::string,a boost::any(for a double and double*)
// and a boost::shared_array<int>
public:
A(double value1, double value2)
{
val[0] = value1;
val[1] = value2;
}
// with normal constructor stuff here, but also
A(A* const& a) // a pointer-to-object "copy"-constructor?!
{
memcpy(this->val, a->val, sizeof(double) * 2 );
// no delete here either...
}
}
它在std :: map中使用(不是指针映射!)
typedef std::map<std::string, A> aMap;
aMap mapOfA;
然后我在代码中找到了很多这些小宝石:
mapOfA.insert(std::make_pair("elite", new A(1.337)));
特别注意A之前的“新”!据我所知,关键字“new”在堆中分配内存,必须再次删除(除了boost指针和类似的东西),我希望它现在仍然正确。 ;)
所以代码在堆上创建一个对象,通过指针将它传递给那个特殊的指针 - 转换 - 复制 - 构造函数,后者依次通过值传递给std :: make_pair,因为地图想要存储整个对象而不是一个指针。到目前为止,我是否理解这一点?出于好奇,我评论说“复制” - 构造函数并且它给出了我预期每个小宝石上的编译器错误(从A *转换为非标量类型A请求)。
鉴于它是用GCC 4.1.2编译的,是否涉及任何机制我不知道这使得这实际上有用吗?在我看来,它只是非常糟糕的做法!它不仅缓慢而且泄漏记忆很多,不是吗?
我改为double数组,因为ppl很多地评论了memcpy功能,这实际上是好的,因为它实际上是一个boost :: shared_array我只是为了示例目的而简化。
答案 0 :(得分:3)
鉴于它是用GCC 4.1.2编译的,是否涉及任何机制我不知道这使得这实际上有用吗?
没有。这只是糟糕的代码。
你可以通过它来清理它(你应该从删除A(A* const& a)
代码开始。)
在我看来,它只是非常糟糕的做法!
它为它生成的每个元素分配/泄漏一个元素。 它还使用memcpy(显然不是赋值?)。
它不仅缓慢而且泄漏记忆很多,不是吗?
是
如果我猜测有人试图在从指针初始化时实现一个移动构造函数,并从中做出一个不完整的,可怕的混乱(可能在C ++ 11之前?)。这只是猜测。
答案 1 :(得分:1)
呸!为什么不放弃memcpy
并简单地使用:
val = a->val;
答案 2 :(得分:1)
您的理解是正确的,此代码是疯了。作者显然不了解C ++内存管理,甚至不了解赋值等基本概念; memcpy
是val = a->val;
如果我不得不猜测,我会说作者误解了必须用new
创建类对象(因为它们在其他流行的语言中),并添加了怪异的构造函数来修复随后的编译错误。
正确的解决方法是删除new
:
mapOfA.insert(std::make_pair("elite", A(1.337)));
或仅1.337
,如果double
的转换应该是隐含的。