繁体   English   中英

使用转换构造函数进行类到类类型转换的程序崩溃

[英]Program for class to class type conversion using conversion constructor crashed

在下面的代码中,我试图将int *类型转换为vector类。 但是在运行程序时,程序在转换构造函数中暂停后终止,以将值从int[]复制到vector::int *v

此外,这是其中一本书中的一个例子。 我一直试图弄清楚这里发生了什么。 任何线索都会有所帮助。

#include<iostream>

using namespace std;

const int size=3;

template <class T>
class vector{
    T*v;
    public:
        vector()
        {
            v=new T[size];
            for(int i=0; i<size; i++){
                cout << "A" << endl;
                v[i]=0;
            }
            cout << "vector 0-arg ctor" << endl;
        }
        vector(T *a) ///////////////////// conversion ctor for type conversion
        {
            for(int i=0; i<size; i++){
                cout << "B" << endl; 

                v[i]=a[i];////////////////// Program exits here 

            }
            cout << "vector 1-arg ctor" << endl;
        }
        T operator*(vector &y)
        {
            T sum=0;
            for(int i=0; i<size; i++){
                cout << "C" << endl;
                sum += this->v[i] * y.v[i];
            }
            return sum;
        }
};

int main(){
    int x[3]={1,2,3};
    int y[3]={4,5,6};
    vector <int> v1;
    vector <int> v2;

    v1=x; ////////////////////// Type conversion from int * -> vector
    v2=y; ////////////////////// int * -> vector

    int R=v1*v2;
    cout << "R : " << R << endl;
    return 0;
}

输出如下 - >

A
A
A
vector 0-arg ctor
A
A
A
vector 0-arg ctor
B

v1=x;

发生两件事:

  1. 使用vector(T *a)构造一个全新的临时vector 这个临时vectorv1没有任何关联
  2. 使用编译器生成的默认赋值运算符将临时vector分配给v1

不幸的是, vector(T *a)不会为v分配或将现有存储分配给v 由于v不指向有效对象,取消引用它会调用未定义行为并且可以做任何事情。 在提问者的计算机上,看起来好像v[i]=a[i]; 写入无效内存并导致崩溃。 要是我们都这么幸运就好了。

解决方案

v分配一些存储空间

vector(T *a): v(new T[size])
{
    for(int i=0; i<size; i++){
        cout << "B" << endl; 
         v[i]=a[i];
    }
    cout << "vector 1-arg ctor" << endl;
}

我以成员初始值设定项列表为例。 可悲的是,它缺乏教学,而且非常有用。

别去尝试

vector(T *a): v(a)
{
}

尽管它看起来很诱人。 在不久的将来某个时候需要编写vector析构函数来防止内存泄漏,无法从提供的动态分配中告诉静态分配的数组x ,如果不调用 Undefined Behaviour 就无法delete该数组默认构造函数,必须delete ed。

既然已经提到了析构函数的话题,那么了解三法则就很重要了。

v1=x;第2步v1=x; 执行任务。 编译器生成的默认赋值运算符非常简单,也非常愚蠢。 它将一个vector准确地复制到另一个vector中。 如果它看到一个指针,它会复制地址,而不是指向的内容。 目标对象指向的任何内容都不会被delete ,并且可能会丢失。 这让您有两个对象指向同一个内存。 改变一个对象现在可以改变另一个对象,随之而来的是混乱。

在此分配之后, v1v将被临时vector替换,从而泄漏v1的原始内存分配。 更糟糕的是,临时vector名副其实并迅速超出范围。 一旦vector具有正常运行的析构函数,临时对象就会将其v带走,并且由于v1和临时对象现在指向相同的内存分配,因此v1v指向无效内存。

需要一个赋值运算符来清理这个混乱。 有关编写赋值运算符的非常简单、非常安全的方法,请参阅Copy and Swap Idiom

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM