簡體   English   中英

使用運算符重載時如何返回結果 +

[英]How do I return results while using operator overloading +

當我使用運算符重載並返回臨時對象時,我有一些代碼讓我感到困惑,它調用了我的復制構造函數,並且出現異常,但是當我返回我的類成員 temp.size 時,它​​調用了我的參數化構造函數 MyClass(int大小),一切正常。 我對它的工作原理以及與之相關的內容感興趣。 代碼如下。

class MyClass
{
private:
    int* data;
    int size;
    
public:
    MyClass()
    {
        size = 0;
    }
    MyClass(int size)
    {
        this->size = size;
        data = new int[size];
        for (size_t i = 0; i < size; i++)
        {
            data[i] = rand();
        }
    }
    MyClass(const MyClass& obj)
    {
        this->size = obj.size;
        this->data = new int[size];
        for (size_t i = 0; i < size; i++)
        {
            data[i] = obj.data[i];
        }
    }
    MyClass operator+(const MyClass& obj)
    {
        MyClass temp;
        temp.size = this->size + obj.size;
        return temp.size;
    }
    friend ostream& operator<<(ostream& os, MyClass& obj);

    ~MyClass()
    {
        delete[]data;
    }
};

ostream& operator<<(ostream & os, MyClass & obj)
{
    os << obj.size;
    return os;
}

int main()
{
    MyClass a(5);
    MyClass b(a);
    MyClass c = a + b;
    cout << c;
    return 0;
}

我看到您的代碼存在幾個問題:

  • 您的默認構造函數未初始化data

  • 您的operator+不會嘗試將值從this->dataobj.datatemp.data ,從而使temp.data未初始化。

  • 您的operator+返回錯誤的MyClass對象。 它麻煩的是准備一個名為tempMyClass對象,然后在退出時完全丟棄temp 通過將temp.size傳遞給return ,您正在通過MyClass(int size)構造函數創建另一個MyClass對象,該構造函數生成所有新的隨機數據。 您需要return您准備的temp對象。 然后編譯器將調用您的復制構造函數在main()中將temp分配給c ,或者它將優化副本以讓operator+直接對c進行操作。

  • 根據 3 規則,您缺少復制賦值運算符。 您的示例中沒有任何內容實際調用復制賦值,但您仍然需要正確實現運算符。 如果您使用的是 C++11 或更高版本,您還應該遵循5 法則,通過添加移動構造函數和移動賦值運算符。 但是,如果您可以更改設計以使用std::vector而不是new[] ,那么您可以遵循0 規則並讓編譯器為您完成所有繁重的工作。

話雖如此,請嘗試更像這樣的事情:

#include <iostream>
#include <algorithm>
#include <utility> // C++11 and later only...
#include <cstdlib>
#include <ctime>    

class MyClass
{
private:
    int* data;
    size_t size;
    
public:
    MyClass(size_t size = 0) : data(NULL), size(size)
    {
        if (size > 0)
        {
            data = new int[size];
            // in C++11 and later, consider using std::uniform_int_distribution instead of rand()!
            std::generate(data, data + size, std::rand);
        }
    }

    MyClass(const MyClass& obj) : data(NULL), size(obj.size)
    {
        if (size > 0)
        {
            data = new int[size];
            std::copy(obj.data, obj.data + obj.size, data);
        }
    }

    // C++11 and later only...
    MyClass(MyClass&& obj) : data(NULL), size(0)
    {
        std::swap(size, obj.size);
        std::swap(data, obj.data);
    }

    ~MyClass()
    {
        delete[] data;
    }

    MyClass& operator=(const MyClass& rhs)
    {
        if (&rhs != this)
        {
            MyClass temp(rhs);
            std::swap(size, temp.size);
            std::swap(data, temp.data);
        }
        return *this;
    }
    
    MyClass& operator=(MyClass&& rhs)
    {
        MyClass temp(std::move(rhs));
        std::swap(size, temp.size);
        std::swap(data, temp.data);
        return *this;
    }

    MyClass operator+(const MyClass& obj) const
    {
        MyClass temp;
        temp.size = size + obj.size;
        if (temp.size > 0)
        {
            temp.data = new int[temp.size];
            std::copy(data, data + size, temp.data);
            std::copy(obj.data, obj.data + obj.size, temp.data + size);
        }
        return temp;
    }

    friend std::ostream& operator<<(std::ostream& os, const MyClass& obj);
};

std::ostream& operator<<(std::ostream& os, const MyClass& obj)
{
    os << obj.size;
    for(size_t i = 0; i < obj.size; ++i)
    {
        os << " " << obj.data[i];
    }
    return os;
}

int main()
{
    std::srand(std::time(0));
    MyClass a(5);
    MyClass b(a);
    MyClass c = a + b;
    std::cout << c;
    return 0;
}

可以簡化為:

#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>

class MyClass
{
private:
    std::vector<int> data;
    
public:
    MyClass(size_t size = 0) : data(size)
    {
        std::generate(data.begin(), data.end(), std::rand);
    }

    MyClass operator+(const MyClass& obj) const
    {
        MyClass temp;
        if (!data.empty() || !obj.data.empty())
        {
            temp.data.reserve(data.size() + obj.data.size());
            temp.data.insert(temp.data.end(), data.begin(), data.end());
            temp.data.insert(temp.data.end(), obj.data.begin(), obj.data.end());
        }
        return temp;
    }

    friend std::ostream& operator<<(std::ostream& os, const MyClass& obj);
};

std::ostream& operator<<(std::ostream& os, const MyClass& obj)
{
    os << obj.size;
    for(size_t i = 0; i < obj.size; ++i)
    {
        os << " " << obj.data[i];
    }
    return os;
}

int main()
{
    std::srand(std::time(0));
    MyClass a(5);
    MyClass b(a);
    MyClass c = a + b;
    std::cout << c;
    return 0;
}

如果你可以使用std::vector ,你的代碼可以變成:

class MyClass {
private:
    vector<int> data;
public:
    MyClass(int size) {
        data.resize(size);
        for (size_t i = 0; i < size; i++) {
            data[i] = rand();
        }
    }
    MyClass operator+(const MyClass& obj) {
        return data.size() + obj.data.size();
    }
    friend ostream& operator<<(ostream& os, MyClass& obj);
};

ostream& operator<<(ostream& os, MyClass& obj) {
    os << obj.data.size();
    return os;
}

否則不要delete未初始化的指針。 (所以要么調用new要么設置為nullptr )。 您不會在默認構造函數中初始化指針,因此請勿在析構函數中調用delete 更改默認構造函數以將data設置為nullptr

    MyClass() {
        data = nullptr;
        size = 0;
    }

當您尚未初始化指針時,也不要從數組中復制。 當您設置size變量時,您不是在創建數組。 您應該創建一個名為setSize的函數並將您的代碼更改為:

    MyClass(int size) {
        data = nullptr;
        setSize(size);
    }
    void setSize(int size) {
        this->size = size;
        delete[] data;
        data = new int[size];
        for (size_t i = 0; i < size; i++) {
            data[i] = rand();
        }
    }
    MyClass operator+(const MyClass& obj) {
        MyClass temp;
        temp.setSize(this->size + obj.size);
        return temp.size;
    }

無論何時需要更改大小,都應該使用setSize函數來確保也創建了數組。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM