簡體   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