[따배C++] 9. 연산자 오버로딩
Created: June 6, 2021 11:26 AM
Tag: RVO, converting constructor, copy constructor, deep copy, explicit, operator overloading, satic_cast typecasts, shallow copy
9.1 산술 연산자 오버로딩 하기
- 오버로딩이 불가능한 연산자:
?
:
::
sizeof
.
.*
- 연산자의 우선순위는 오버로딩 하지 못한다.
- 직관적으로 받아들일 수 있는 경우로만 사용해야 한다. 애메할 때는 함수를 사용하자.
^
연산자는 우선순위가 매우 낮으므로 오버로딩 하는것을 지양해야 한다. (사용하고자 한다면 괄호로 싸주어야 한다.)
=, [], (), ->
은 member function으로만 구현할 수 있다.
#include <iostream>
using namespace std;
class Cents
{
private:
int m_cents;
public:
Cents(int cents = 0) { m_cents = cents; }
int getCents() const { return m_cents; }
int &getCents() { return m_cents; }
Cents operator + (const Cents &c2) // member function으로 구현
{
return (Cents(this->m_cents + c2.m_cents));
}
};
int main(void)
{
Cents cents1(6);
Cents cents2(8);
cout << (cents1 + cents2 + Cents(6) + Cents(10)).getCents() << endl;
}
9.2 입출력 연산자 오버로딩 하기(파일 입출력)
#include <iostream>
#include <fstream>
using namespace std;
class Point
{
private:
double m_x, m_y, m_z;
public:
Point(double x = 0.0, double y = 0.0, double z = 0.0)
: m_x(x), m_y(y), m_z(z)
{}
friend std::ostream &operator << (std::ostream &out, const Point &point)
{
out << "( " << point.m_x << " " << point.m_y << " " << point.m_z << " )";
return (out); // for chaining
}
};
int main(void)
{
ofstream of("out.txt"); // output file stream
Point p1(0.0, 0.1, 0.2), p2(3.4, 1.5, 2.0);
cout << p1 << " " << p2 << endl;
of << p1 << " " << p2 << endl;
of.close();
return (0);
}
9.3 단항 연산자 - ! 오버로딩 하기
#include <iostream>
#include <fstream>
using namespace std;
class Cents
{
private:
int m_cents;
public:
Cents(int cents = 0) { m_cents = cents; }
int getCents() const { return m_cents; }
int &getCents() { return m_cents; }
Cents operator - () const
{
return Cents(-m_cents);
}
bool operator ! () const // <-
{
return ((m_cents == 0) ? true : false);
}
friend std::ostream &operator << (std::ostream &out, const Cents ¢s)
{
out << cents.m_cents;
return (out);
}
};
int main(void)
{
Cents cents1(6);
Cents cents2(0);
cout << cents1 << endl;
cout << -cents1 << endl;
cout << -Cents(-10) << endl;
cout << !cents1 << " " << !cents2 << endl;
return (0);
}
9.4 비교 연산자 오버로딩 하기 ==, !=, >, >=
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
class Cents
{
private:
int m_cents;
public:
Cents(int cents = 0) { m_cents = cents; }
int getCents() const { return m_cents; }
int &getCents() { return m_cents; }
friend bool operator == (const Cents &c1, const Cents &c2)
{
return (c1.m_cents == c2.m_cents);
}
friend std::ostream &operator << (std::ostream &out, const Cents ¢s)
{
out << cents.m_cents;
return (out); // for chaining
}
};
int main(void)
{
Cents cents1(6);
Cents cents2(6);
if (cents1 == cents2)
cout << "equal" << endl;
cout << std::boolalpha;
return (0);
}
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
class Cents
{
private:
int m_cents;
public:
Cents(int cents = 0) { m_cents = cents; }
int getCents() const { return m_cents; }
int &getCents() { return m_cents; }
friend bool operator == (const Cents &c1, const Cents &c2)
{
return (c1.m_cents == c2.m_cents);
}
friend bool operator < (const Cents &c1, const Cents &c2)
// 반드시 less than으로 구현되어야 한다!
{
return (c1.m_cents < c2.m_cents);
}
friend std::ostream &operator << (std::ostream &out, const Cents ¢s)
{
out << cents.m_cents;
return (out);
}
};
int main(void)
{
vector<Cents> arr(20);
for (unsigned i = 0; i < 20; ++i)
arr[i].getCents() = i;
std::random_shuffle(begin(arr), end(arr));
for (auto &e : arr)
cout << e << " ";
cout << endl;
// cents들 끼리 크기비교 불가능 -> 연산자 오버로딩
std::sort(begin(arr), end(arr));
for (auto &e : arr)
cout << e << " ";
cout << endl;
return (0);
}
9.5 증감 연산자 오버로딩 하기
#include <iostream>
using namespace std;
class Digit
{
private:
int m_digit;
public:
Digit(int digit = 0) : m_digit(digit) {}
// prefix
Digit &operator ++ ()
{
++m_digit;
return (*this); // 자기 자신을 반환
}
// postfix
Digit operator ++ (int) // 여기서 int는 dummy로 사용된다
{
Digit temp(m_digit);
++(*this);
return (temp);
}
friend ostream &operator << (ostream &out, const Digit &d)
{
out << d.m_digit;
return (out);
}
};
int main(void)
{
Digit d(5);
cout << ++d << endl;
cout << d << endl;
cout << d++ << endl;
cout << d << endl;
return (0);
}
9.6 첨자 연산자 오버로딩 하기 [] subscript operator
#include <iostream>
#include <cassert>
using namespace std;
class IntList
{
private:
int m_list[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
public:
int &operator [] (const int index)
{
assert(index >= 0);
assert(index < 10);
return (m_list[index]);
}
const int &operator [] (const int index) const
{
return (m_list[index]);
}
};
int main(void)
{
const IntList my_list;
cout << my_list[3] << endl;
IntList *list = new IntList;
list[3] = 10; // not ok
(*list)[3] = 10; // ok
return (0);
}
💡 `assert`를 사용하는것이 조건문을 사용하는 것보다 퍼포먼스에 유리하다.
9.7 괄호 연산자 function object, functer
?
:
::
sizeof
.
.*
^
연산자는 우선순위가 매우 낮으므로 오버로딩 하는것을 지양해야 한다. (사용하고자 한다면 괄호로 싸주어야 한다.)=, [], (), ->
은 member function으로만 구현할 수 있다.#include <iostream>
using namespace std;
class Cents
{
private:
int m_cents;
public:
Cents(int cents = 0) { m_cents = cents; }
int getCents() const { return m_cents; }
int &getCents() { return m_cents; }
Cents operator + (const Cents &c2) // member function으로 구현
{
return (Cents(this->m_cents + c2.m_cents));
}
};
int main(void)
{
Cents cents1(6);
Cents cents2(8);
cout << (cents1 + cents2 + Cents(6) + Cents(10)).getCents() << endl;
}
#include <iostream>
#include <fstream>
using namespace std;
class Point
{
private:
double m_x, m_y, m_z;
public:
Point(double x = 0.0, double y = 0.0, double z = 0.0)
: m_x(x), m_y(y), m_z(z)
{}
friend std::ostream &operator << (std::ostream &out, const Point &point)
{
out << "( " << point.m_x << " " << point.m_y << " " << point.m_z << " )";
return (out); // for chaining
}
};
int main(void)
{
ofstream of("out.txt"); // output file stream
Point p1(0.0, 0.1, 0.2), p2(3.4, 1.5, 2.0);
cout << p1 << " " << p2 << endl;
of << p1 << " " << p2 << endl;
of.close();
return (0);
}
9.3 단항 연산자 - ! 오버로딩 하기
#include <iostream>
#include <fstream>
using namespace std;
class Cents
{
private:
int m_cents;
public:
Cents(int cents = 0) { m_cents = cents; }
int getCents() const { return m_cents; }
int &getCents() { return m_cents; }
Cents operator - () const
{
return Cents(-m_cents);
}
bool operator ! () const // <-
{
return ((m_cents == 0) ? true : false);
}
friend std::ostream &operator << (std::ostream &out, const Cents ¢s)
{
out << cents.m_cents;
return (out);
}
};
int main(void)
{
Cents cents1(6);
Cents cents2(0);
cout << cents1 << endl;
cout << -cents1 << endl;
cout << -Cents(-10) << endl;
cout << !cents1 << " " << !cents2 << endl;
return (0);
}
9.4 비교 연산자 오버로딩 하기 ==, !=, >, >=
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
class Cents
{
private:
int m_cents;
public:
Cents(int cents = 0) { m_cents = cents; }
int getCents() const { return m_cents; }
int &getCents() { return m_cents; }
friend bool operator == (const Cents &c1, const Cents &c2)
{
return (c1.m_cents == c2.m_cents);
}
friend std::ostream &operator << (std::ostream &out, const Cents ¢s)
{
out << cents.m_cents;
return (out); // for chaining
}
};
int main(void)
{
Cents cents1(6);
Cents cents2(6);
if (cents1 == cents2)
cout << "equal" << endl;
cout << std::boolalpha;
return (0);
}
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
class Cents
{
private:
int m_cents;
public:
Cents(int cents = 0) { m_cents = cents; }
int getCents() const { return m_cents; }
int &getCents() { return m_cents; }
friend bool operator == (const Cents &c1, const Cents &c2)
{
return (c1.m_cents == c2.m_cents);
}
friend bool operator < (const Cents &c1, const Cents &c2)
// 반드시 less than으로 구현되어야 한다!
{
return (c1.m_cents < c2.m_cents);
}
friend std::ostream &operator << (std::ostream &out, const Cents ¢s)
{
out << cents.m_cents;
return (out);
}
};
int main(void)
{
vector<Cents> arr(20);
for (unsigned i = 0; i < 20; ++i)
arr[i].getCents() = i;
std::random_shuffle(begin(arr), end(arr));
for (auto &e : arr)
cout << e << " ";
cout << endl;
// cents들 끼리 크기비교 불가능 -> 연산자 오버로딩
std::sort(begin(arr), end(arr));
for (auto &e : arr)
cout << e << " ";
cout << endl;
return (0);
}
9.5 증감 연산자 오버로딩 하기
#include <iostream>
using namespace std;
class Digit
{
private:
int m_digit;
public:
Digit(int digit = 0) : m_digit(digit) {}
// prefix
Digit &operator ++ ()
{
++m_digit;
return (*this); // 자기 자신을 반환
}
// postfix
Digit operator ++ (int) // 여기서 int는 dummy로 사용된다
{
Digit temp(m_digit);
++(*this);
return (temp);
}
friend ostream &operator << (ostream &out, const Digit &d)
{
out << d.m_digit;
return (out);
}
};
int main(void)
{
Digit d(5);
cout << ++d << endl;
cout << d << endl;
cout << d++ << endl;
cout << d << endl;
return (0);
}
9.6 첨자 연산자 오버로딩 하기 [] subscript operator
#include <iostream>
#include <cassert>
using namespace std;
class IntList
{
private:
int m_list[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
public:
int &operator [] (const int index)
{
assert(index >= 0);
assert(index < 10);
return (m_list[index]);
}
const int &operator [] (const int index) const
{
return (m_list[index]);
}
};
int main(void)
{
const IntList my_list;
cout << my_list[3] << endl;
IntList *list = new IntList;
list[3] = 10; // not ok
(*list)[3] = 10; // ok
return (0);
}
💡 `assert`를 사용하는것이 조건문을 사용하는 것보다 퍼포먼스에 유리하다.
9.7 괄호 연산자 function object, functer
#include <iostream>
#include <fstream>
using namespace std;
class Cents
{
private:
int m_cents;
public:
Cents(int cents = 0) { m_cents = cents; }
int getCents() const { return m_cents; }
int &getCents() { return m_cents; }
Cents operator - () const
{
return Cents(-m_cents);
}
bool operator ! () const // <-
{
return ((m_cents == 0) ? true : false);
}
friend std::ostream &operator << (std::ostream &out, const Cents ¢s)
{
out << cents.m_cents;
return (out);
}
};
int main(void)
{
Cents cents1(6);
Cents cents2(0);
cout << cents1 << endl;
cout << -cents1 << endl;
cout << -Cents(-10) << endl;
cout << !cents1 << " " << !cents2 << endl;
return (0);
}
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
class Cents
{
private:
int m_cents;
public:
Cents(int cents = 0) { m_cents = cents; }
int getCents() const { return m_cents; }
int &getCents() { return m_cents; }
friend bool operator == (const Cents &c1, const Cents &c2)
{
return (c1.m_cents == c2.m_cents);
}
friend std::ostream &operator << (std::ostream &out, const Cents ¢s)
{
out << cents.m_cents;
return (out); // for chaining
}
};
int main(void)
{
Cents cents1(6);
Cents cents2(6);
if (cents1 == cents2)
cout << "equal" << endl;
cout << std::boolalpha;
return (0);
}
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
class Cents
{
private:
int m_cents;
public:
Cents(int cents = 0) { m_cents = cents; }
int getCents() const { return m_cents; }
int &getCents() { return m_cents; }
friend bool operator == (const Cents &c1, const Cents &c2)
{
return (c1.m_cents == c2.m_cents);
}
friend bool operator < (const Cents &c1, const Cents &c2)
// 반드시 less than으로 구현되어야 한다!
{
return (c1.m_cents < c2.m_cents);
}
friend std::ostream &operator << (std::ostream &out, const Cents ¢s)
{
out << cents.m_cents;
return (out);
}
};
int main(void)
{
vector<Cents> arr(20);
for (unsigned i = 0; i < 20; ++i)
arr[i].getCents() = i;
std::random_shuffle(begin(arr), end(arr));
for (auto &e : arr)
cout << e << " ";
cout << endl;
// cents들 끼리 크기비교 불가능 -> 연산자 오버로딩
std::sort(begin(arr), end(arr));
for (auto &e : arr)
cout << e << " ";
cout << endl;
return (0);
}
9.5 증감 연산자 오버로딩 하기
#include <iostream>
using namespace std;
class Digit
{
private:
int m_digit;
public:
Digit(int digit = 0) : m_digit(digit) {}
// prefix
Digit &operator ++ ()
{
++m_digit;
return (*this); // 자기 자신을 반환
}
// postfix
Digit operator ++ (int) // 여기서 int는 dummy로 사용된다
{
Digit temp(m_digit);
++(*this);
return (temp);
}
friend ostream &operator << (ostream &out, const Digit &d)
{
out << d.m_digit;
return (out);
}
};
int main(void)
{
Digit d(5);
cout << ++d << endl;
cout << d << endl;
cout << d++ << endl;
cout << d << endl;
return (0);
}
9.6 첨자 연산자 오버로딩 하기 [] subscript operator
#include <iostream>
#include <cassert>
using namespace std;
class IntList
{
private:
int m_list[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
public:
int &operator [] (const int index)
{
assert(index >= 0);
assert(index < 10);
return (m_list[index]);
}
const int &operator [] (const int index) const
{
return (m_list[index]);
}
};
int main(void)
{
const IntList my_list;
cout << my_list[3] << endl;
IntList *list = new IntList;
list[3] = 10; // not ok
(*list)[3] = 10; // ok
return (0);
}
💡 `assert`를 사용하는것이 조건문을 사용하는 것보다 퍼포먼스에 유리하다.
9.7 괄호 연산자 function object, functer
#include <iostream>
using namespace std;
class Digit
{
private:
int m_digit;
public:
Digit(int digit = 0) : m_digit(digit) {}
// prefix
Digit &operator ++ ()
{
++m_digit;
return (*this); // 자기 자신을 반환
}
// postfix
Digit operator ++ (int) // 여기서 int는 dummy로 사용된다
{
Digit temp(m_digit);
++(*this);
return (temp);
}
friend ostream &operator << (ostream &out, const Digit &d)
{
out << d.m_digit;
return (out);
}
};
int main(void)
{
Digit d(5);
cout << ++d << endl;
cout << d << endl;
cout << d++ << endl;
cout << d << endl;
return (0);
}
#include <iostream>
#include <cassert>
using namespace std;
class IntList
{
private:
int m_list[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
public:
int &operator [] (const int index)
{
assert(index >= 0);
assert(index < 10);
return (m_list[index]);
}
const int &operator [] (const int index) const
{
return (m_list[index]);
}
};
int main(void)
{
const IntList my_list;
cout << my_list[3] << endl;
IntList *list = new IntList;
list[3] = 10; // not ok
(*list)[3] = 10; // ok
return (0);
}
💡 `assert`를 사용하는것이 조건문을 사용하는 것보다 퍼포먼스에 유리하다.
9.7 괄호 연산자 function object, functer
마치 함수인것 처럼 사용할 수 있다. (Functor)
#include <iostream>
using namespace std;
class Accumulator
{
private:
int m_counter = 0;
public:
int operator()(int i) { return (m_counter += i); }
};
int main(void)
{
Accumulator acc;
cout << acc(10) << endl;
cout << acc(20) << endl;
return (0);
}
9.8 형변환을 오버로딩 하기 static_cast typecasts
#include <iostream>
using namespace std;
class Cents
{
private:
int m_cents;
public:
Cents(int cents = 0)
{
m_cents = cents;
}
int getCents() { return (m_cents); }
void setCents(int cents) { m_cents = cents; }
operator int()
{
cout << "cast here" << endl;
return m_cents;
}
};
class Dollar
{
private:
int m_dollars = 0;
public:
Dollar(const int &input) : m_dollars(input) {}
operator Cents()
{
return (Cents(m_dollars * 100));
}
};
void printInt(const int &value)
{
cout << value << endl;
}
int main(void)
{
Dollar dol(2);
Cents cents = dol;
printInt(cents);
return (0);
}
9.9 복사 생성자, 복사 초기화, 반환값최적화 RVO return value optimization
#include <iostream>
#include <cassert>
using namespace std;
class Fraction
{
private:
int m_numerator;
int m_denominator;
public:
Fraction(int num = 0, int den = 1)
: m_numerator(num), m_denominator(den)
{
assert(den != 0);
}
Fraction(const Fraction &fraction) // copy constructor // 자신과 똑같은 타입의 인스턴스가 인풋으로 들어옴
: m_numerator(fraction.m_numerator), m_denominator(fraction.m_denominator)
{
cout << "copy constructor called" << endl;
}
friend std::ostream &operator << (std::ostream &out, const Fraction &f)
{
out << f.m_numerator << " / " << f.m_denominator << endl;
return (out);
}
};
Fraction doSomething()
{
Fraction temp(1, 2);
cout << &temp << endl;
return (temp);
}
int main(void)
{
Fraction frac(3, 5);
Fraction fr_copy = frac;
cout << frac << " " << fr_copy << endl;
// ============================================================
// RVO by compiler
Fraction result = doSomething();
cout << &result << endl;
cout << result << endl;
return (0);
}
9.10 변환 생성자 converting constructor, explicit, delete
#include <iostream>
#include <cassert>
using namespace std;
class Fraction
{
private:
int m_numerator;
int m_denominator;
public:
Fraction(char) = delete; // 파라미터 금지
Fraction(int num = 0, int den = 1)
// explicit Fraction(int num = 0, int den = 1)
: m_numerator(num), m_denominator(den)
{
assert(den != 0);
}
Fraction(const Fraction &fraction) // copy constructor
: m_numerator(fraction.m_numerator), m_denominator(fraction.m_denominator)
{
cout << "copy constructor called" << endl;
}
friend std::ostream &operator << (std::ostream &out, const Fraction &f)
{
out << f.m_numerator << " / " << f.m_denominator << endl;
return (out);
}
};
void doSomething(Fraction frac)
{
cout << frac << endl;
}
int main(void)
{
Fraction frac(7);
doSomething(frac);
doSomething(7);
return (0);
}
9.12 이니셜라이져 리스트 initializer list
#include <iostream>
using namespace std;
class Cents
{
private:
int m_cents;
public:
Cents(int cents = 0)
{
m_cents = cents;
}
int getCents() { return (m_cents); }
void setCents(int cents) { m_cents = cents; }
operator int()
{
cout << "cast here" << endl;
return m_cents;
}
};
class Dollar
{
private:
int m_dollars = 0;
public:
Dollar(const int &input) : m_dollars(input) {}
operator Cents()
{
return (Cents(m_dollars * 100));
}
};
void printInt(const int &value)
{
cout << value << endl;
}
int main(void)
{
Dollar dol(2);
Cents cents = dol;
printInt(cents);
return (0);
}
#include <iostream>
#include <cassert>
using namespace std;
class Fraction
{
private:
int m_numerator;
int m_denominator;
public:
Fraction(int num = 0, int den = 1)
: m_numerator(num), m_denominator(den)
{
assert(den != 0);
}
Fraction(const Fraction &fraction) // copy constructor // 자신과 똑같은 타입의 인스턴스가 인풋으로 들어옴
: m_numerator(fraction.m_numerator), m_denominator(fraction.m_denominator)
{
cout << "copy constructor called" << endl;
}
friend std::ostream &operator << (std::ostream &out, const Fraction &f)
{
out << f.m_numerator << " / " << f.m_denominator << endl;
return (out);
}
};
Fraction doSomething()
{
Fraction temp(1, 2);
cout << &temp << endl;
return (temp);
}
int main(void)
{
Fraction frac(3, 5);
Fraction fr_copy = frac;
cout << frac << " " << fr_copy << endl;
// ============================================================
// RVO by compiler
Fraction result = doSomething();
cout << &result << endl;
cout << result << endl;
return (0);
}
9.10 변환 생성자 converting constructor, explicit, delete
#include <iostream>
#include <cassert>
using namespace std;
class Fraction
{
private:
int m_numerator;
int m_denominator;
public:
Fraction(char) = delete; // 파라미터 금지
Fraction(int num = 0, int den = 1)
// explicit Fraction(int num = 0, int den = 1)
: m_numerator(num), m_denominator(den)
{
assert(den != 0);
}
Fraction(const Fraction &fraction) // copy constructor
: m_numerator(fraction.m_numerator), m_denominator(fraction.m_denominator)
{
cout << "copy constructor called" << endl;
}
friend std::ostream &operator << (std::ostream &out, const Fraction &f)
{
out << f.m_numerator << " / " << f.m_denominator << endl;
return (out);
}
};
void doSomething(Fraction frac)
{
cout << frac << endl;
}
int main(void)
{
Fraction frac(7);
doSomething(frac);
doSomething(7);
return (0);
}
9.12 이니셜라이져 리스트 initializer list
#include <iostream>
#include <cassert>
using namespace std;
class Fraction
{
private:
int m_numerator;
int m_denominator;
public:
Fraction(char) = delete; // 파라미터 금지
Fraction(int num = 0, int den = 1)
// explicit Fraction(int num = 0, int den = 1)
: m_numerator(num), m_denominator(den)
{
assert(den != 0);
}
Fraction(const Fraction &fraction) // copy constructor
: m_numerator(fraction.m_numerator), m_denominator(fraction.m_denominator)
{
cout << "copy constructor called" << endl;
}
friend std::ostream &operator << (std::ostream &out, const Fraction &f)
{
out << f.m_numerator << " / " << f.m_denominator << endl;
return (out);
}
};
void doSomething(Fraction frac)
{
cout << frac << endl;
}
int main(void)
{
Fraction frac(7);
doSomething(frac);
doSomething(7);
return (0);
}
이니셜라이져 리스트는 클래스와 같은 사용자 정의 자료형에서 생성자나 대입 연산자를 만들 때 편리하게 사용할 수 있다.
#include <iostream>
#include <cassert>
#include <initializer_list>
using namespace std;
class IntArray
{
private:
unsigned m_length = 0;
int *m_data = nullptr;
public:
IntArray(unsigned length)
: m_length(length)
{
m_data = new int[length];
}
IntArray(const std::initializer_list<int> &list)
:IntArray(list.size())
{
int count = 0;
for (auto &element : list)
{
m_data[count] = element;
++count;
}
// for (unsigned count = 0; count < list.size(); ++count)
// m_data[count] = list[count]; // error
}
~IntArray()
{
delete[] this->m_data;
}
friend ostream &operator << (ostream &out, IntArray &arr)
{
for (unsigned i = 0; i < arr.m_length; ++i)
out << arr.m_data[i] << " ";
out << endl;
return (out);
}
};
int main(void)
{
int my_arr1[5] = { 1, 2, 3, 4, 5 }; // init list // 기본자료형
int *my_arr2 = new int [5]{ 1 , 2, 3, 4, 5 }; // 동적할당
auto il = { 10, 20, 30 }; // 자동으로 init list 임을 인식
IntArray int_array { 1, 2, 3, 4, 5 };
cout << int_array << endl;
return (0);
}
9.11 대입 연산자 오버로딩, 깊은 복사 deep copy, 얕은 복사 shallow copy
동적할당된 메모리에 대한 포인터 변수를 맴버로서 가지고 있는 클래스에서는 복사, 대입에서 깊은/얕은 복사에 따라 대입 연산자 오버로딩이 까다로워 진다. 이러한 문제에 대해 직접 고민할 일은 없지만 이해하는것은 필요하다.
#include <cassert>
#include <iostream>
using namespace std;
class MyString
{
//private:
public:
char *m_data = nullptr; // 얕은 복사
int m_length = 0;
public:
MyString(const char *source = "")
{
assert(source);
m_length = std::strlen(source) + 1;
m_data = new char[m_length];
for (int i = 0; i < m_length; ++i)
m_data[i] = source[i];
m_data[m_length - 1] = '\0';
}
MyString(const MyString &source) // copy constructor
{
cout << "copy constructor " << endl;
m_length = source.m_length;
if (source.m_data != nullptr) // 메모리를 다시 새로 할당받고 내용을 복사 == 깊은 복사
{
m_data = new char[m_length];
for (int i = 0; i < m_length; ++i)
m_data[i] = source.m_data[i];
}
else
m_data = nullptr; // 0 대신 null ptr을 사용하는것이 최신문법
}
MyString &operator = (const MyString &source)
{
// shallow copy
// this->m_data = source.m_data;
// this->m_length = source.m_length;
cout << "assignment operator " << endl;
if (this == &source) // prevent self-assignment
return (*this);
delete[] m_data; // 이미 메모리를 가지고 있었을 수도 있음
m_length = source.m_length;
if (source.m_data != nullptr)
{
m_data = new char[m_length];
for (int i = 0; i < m_length; ++i)
m_data[i] = source.m_data[i];
}
else
m_data = nullptr;
return (*this);
}
~MyString()
{
delete[] m_data;
}
char *getString() { return (m_data); }
int getLength() { return (m_length); }
};
int main(void)
{
MyString hello("Hello");
MyString str1(hello); // MyString str1 = hello;
MyString str2;
str2 = hello; // 할당 형태에 따라 다르다
// cout << (int *)hello.m_data << endl;
// cout << hello.getString() << endl;
{
MyString copy = hello; // 주소를 말그대로 복사만
cout << (int *)copy.m_data << endl;
cout << copy.getString() << endl;
}
cout << hello.getString() << endl;
return (0);
}
Author And Source
이 문제에 관하여([따배C++] 9. 연산자 오버로딩), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@24siefil/따배C-9.-연산자-오버로딩저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)