使用转换构造函数进行 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;
发生了两件事:
- 使用
vector(T *a)
构建了一个全新的临时vector
。这个临时 vector
与 v1
没有任何关联
- 使用 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 不调用未定义行为,来自默认构造函数提供的动态分配,必须 delete
ed.
并且由于析构函数的话题已经出现,因此了解 Rule of Three 很重要。
v1=x;
的第 2 步执行分配。 compiler-generated 默认赋值运算符非常简单也非常愚蠢。它将一个 vector
中的内容准确地复制到另一个。如果它看到一个指针,它会复制地址,而不是指向的内容。无论目标对象指向什么,都没有 delete
ed 并且可能丢失了。这使您有两个对象指向同一内存。改变一个对象现在可以改变另一个对象,随之而来的是混乱。
此分配后 v1
的 v
将被临时 vector
替换,从而泄漏 v1
的原始内存分配。更糟糕的是,临时 vector
名副其实,很快就超出了范围。一旦 vector
有一个正在运行的析构函数,临时文件将带走它的 v
,并且由于 v1
和临时文件现在指向相同的内存分配,v1
的 v
指向无效内存。
需要一个赋值运算符来清理这个混乱。请参阅 Copy and Swap Idiom 以了解一种非常简单、非常安全的编写赋值运算符的方法。
在下面的代码中,我试图将 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;
发生了两件事:
- 使用
vector(T *a)
构建了一个全新的临时vector
。这个临时vector
与v1
没有任何关联
- 使用 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 不调用未定义行为,来自默认构造函数提供的动态分配,必须 delete
ed.
并且由于析构函数的话题已经出现,因此了解 Rule of Three 很重要。
v1=x;
的第 2 步执行分配。 compiler-generated 默认赋值运算符非常简单也非常愚蠢。它将一个 vector
中的内容准确地复制到另一个。如果它看到一个指针,它会复制地址,而不是指向的内容。无论目标对象指向什么,都没有 delete
ed 并且可能丢失了。这使您有两个对象指向同一内存。改变一个对象现在可以改变另一个对象,随之而来的是混乱。
此分配后 v1
的 v
将被临时 vector
替换,从而泄漏 v1
的原始内存分配。更糟糕的是,临时 vector
名副其实,很快就超出了范围。一旦 vector
有一个正在运行的析构函数,临时文件将带走它的 v
,并且由于 v1
和临时文件现在指向相同的内存分配,v1
的 v
指向无效内存。
需要一个赋值运算符来清理这个混乱。请参阅 Copy and Swap Idiom 以了解一种非常简单、非常安全的编写赋值运算符的方法。