[英]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->data
和obj.data
到temp.data
,從而使temp.data
未初始化。
您的operator+
返回錯誤的MyClass
對象。 它麻煩的是准備一個名為temp
的MyClass
對象,然后在退出時完全丟棄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.