在下面的代码中,我试图将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;
发生两件事:
vector
使用构造了一个全新的临时文件vector(T *a)
。此临时vector
绝不与v1
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
(delete
如果不调用Undefined Behaviour便无法编辑该数组),必须delete
编辑。
既然已经出现了破坏者的话题,那么了解三人制就很重要。
步骤2的v1=x;
执行分配。编译器生成的默认赋值运算符非常简单且非常愚蠢。它精确地vector
将彼此之间的内容复制。如果看到指针,它将复制地址,而不是所指向的地址。无论目标对象指向什么对象,都不会delete
ed并可能丢失。这样就剩下两个指向相同内存的对象。现在,更改一个对象可以更改另一个对象,从而造成混乱。
这个任务后v1
的v
将被替换为临时vector
的,泄漏v1
的原始内存分配。更糟糕的是,临时vector
名称不辜负名称,并迅速超出范围。一旦vector
具有正常运行的析构函数,则临时文件将v
随其使用,并且由于v1
和临时文件现在指向相同的内存分配,因此将v1
sv
指向无效的内存。
需要指派操作员来清理此混乱情况。有关编写赋值运算符的非常简单,非常安全的方法,请参见复制和交换惯用语。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句