CArray不会调用内存重分配的复制构造函数,现在什么? [英] CArray doesn't call copy constructors on memory reallocations, now what?

查看:162
本文介绍了CArray不会调用内存重分配的复制构造函数,现在什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个类需要调用复制构造函数来创建正确的副本:

  struct CWeird 
{
CWeird(){number = 47; target =& number; }

CWeird(const CWeird& other):number(other.number),target(& number){}

const CWeird& operator =(const CWeird& w){number = w.number; return * this; }

void output()
{
printf(%d%d \\\
,* target,number)
}

int * target,number;
};现在的麻烦是,当重新分配内存时,CArray不会在其元素上调用复制构造函数(只有memcpy()从旧的内存到新的),例如此代码

  CArray< CWeird>一个; 
a.SetSize(1);
a [0] .output();

a.SetSize(2);
a [0] .output();

会导致

 code> 47 47 
-572662307 47

为什么std :: vector可以正确复制相同的对象,CArray不能?这里的教训是什么?我应该只使用不需要显式复制构造函数的类吗?

解决方案

复制的指针仍然指向原始数字,其中没有更长的存在,因为数组已经由于调整大小重新分配。



我猜猜CArray使用赋值,而不是复制构造。定义赋值运算符以查看是否可以修复它:

  CWeird& operator =(CWeird w){swap(w); return * this; } 
void swap(CWeird& w){int t = number; number = w.number; w.number = t; }

这通常是一个好主意,以避免复制构造和赋值之间不一致的行为。



FYI,上述代码使用惯用的方法来实现具有强大的异常安全保证的赋值语义:


  1. 返回非const引用是 operator = 的标准,因为它匹配原始类型的语义。

  2. 按值传递参数是最简单的方法来创建原始副本,并保证如果副本构造函数失败,此对象不会受到影响。

  3. 对交换的调用使用此对象切换传入的副本,从而不会抛出异常,从而以完全异常安全的方式执行赋值。

在这种情况下,只是分配数字会更简单,但我习惯性地实现我的所有分配,以避免被抓住我的裤子,如果一个未来的维护者可以复制投掷一个例外。


Suppose I have a class that requires copy constructor to be called to make a correct copy of:

struct CWeird
{
    CWeird() { number = 47; target = &number; }

    CWeird(const CWeird &other) : number(other.number), target(&number) { }

    const CWeird& operator=(const CWeird &w) { number = w.number; return *this; }

    void output()
    {
        printf("%d %d\n", *target, number);
    }

    int *target, number;
};

Now the trouble is that CArray doesn't call copy constructors on its elements when reallocating memory (only memcpy from the old memory to the new), e.g. this code

CArray<CWeird> a;
a.SetSize(1);
a[0].output();

a.SetSize(2);
a[0].output();

results in

47 47
-572662307 47

I don't get this. Why is it that std::vector can copy the same objects properly and CArray can't? What's the lesson here? Should I use only classes that don't require explicit copy constructors? Or is it a bad idea to use CArray for anything serious?

解决方案

The copied pointer still points to the original number, which no longer exists, since the array has been reallocated due to the resize.

I'm guessing that CArray uses assignment rather than copy-construction. Define an assignment operator to see if this fixes it:

CWeird& operator=(CWeird w) { swap(w); return *this; }
void swap(CWeird& w) { int t = number; number = w.number; w.number = t; }

It's generally a good idea to do this anyway, to avoid inconsistent behaviour between copy-construction and assignment.

FYI, the above code uses an idiomatic approach to implementing assignment semantics with strong exception-safety guarantees:

  1. Returning a non-const reference is very much the standard for operator=, since it matches the semantics of primitive types.
  2. Passing the parameter by value is the easiest way to make a copy of the original, and guarantees that this object won't be affected if the copy constructor fails.
  3. The call to swap switches the passed-in copy with this object in a way that will never throw an exception, thus effecting the assignment in a completely exception-safe manner.

In this case, it would be simpler to just assign the number, but I habitually implement all my assignments this way to avoid being caught with my pants down if a future maintainer makes it possible for copying to throw an exception.

这篇关于CArray不会调用内存重分配的复制构造函数,现在什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆