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

Program for class to class type conversion using conversion constructor crashed

在下面的代码中,我试图将 int * 类型转换为 vector class。但是在 运行 程序中,程序在转换构造函数暂停以将值从 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. 没有任何关联
  3. 使用 compiler-generated 默认赋值运算符将临时 vector 赋值给 v1

不幸的是,vector(T *a) 没有为 v 分配或将现有存储分配给 v。由于 v 没有指向有效对象,取消引用它会调用 Undefined Behaviour 并且可以做任何事情。在提问者的计算机上,看起来 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;
}

我以Member Initializer List为例。可悲的是 under-taught 并且非常有用。

请勿尝试

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

虽然看起来很诱人。 vector 近期需要编写防止内存泄漏的析构函数没办法告诉静态分配的数组x,不能delete ]ed 不调用未定义行为,来自默认构造函数提供的动态分配,必须 deleteed.

并且由于析构函数的话题已经出现,因此了解 Rule of Three 很重要。

v1=x; 的第 2 步执行分配。 compiler-generated 默认赋值运算符非常简单也非常愚蠢。它将一个 vector 中的内容准确地复制到另一个。如果它看到一个指针,它会复制地址,而不是指向的内容。无论目标对象指向什么,都没有 deleteed 并且可能丢失了。这使您有两个对象指向同一内存。改变一个对象现在可以改变另一个对象,随之而来的是混乱。

此分配后 v1v 将被临时 vector 替换,从而泄漏 v1 的原始内存分配。更糟糕的是,临时 vector 名副其实,很快就超出了范围。一旦 vector 有一个正在运行的析构函数,临时文件将带走它的 v,并且由于 v1 和临时文件现在指向相同的内存分配,v1v 指向无效内存。

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