-
카테고리
-
세부 분야
프로그래밍 언어
-
해결 여부
해결됨
연습문제 질문있습니다.
22.09.27 04:51 작성 조회수 187
0
IntArray& operator = (const std::initializer_list<int>& list)
{
cout << "Assignment operator " << endl;
delete[] m_data;
m_length = list.size();
m_data = new int[m_length];
int count = 0;
for (auto& element : list)
{
m_data[count] = element;
++count;
}
return *this;
}
연습문제로 이렇게 짜봤는데 m_data[count] = element; 부분에서 buffer overrun이 발생한다고 나옵니다. 그런데 IntArray(const std::initializer_list<int>& list)를 만들 때도 똑같은 코드가 쓰였는데 이때는 왜 에러메시지가 발생하지 않았는지 궁금합니다.
답변을 작성해보세요.
0
thd2tn
질문자2022.09.29
// 기본 자료형으로 array를 만들 때는 initializer_list를 이용해서 값을 편하게 초기화할 수가 있었다.
// 이번에는 class 같은 사용자 정의 자료형에서 생성자나 대입 연산자를 만들 때 편하게 사용할 수 있는 std::initilalizer_list 사용법에 대해서 알아본다.
#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())
// 다른 생성자를 호출해서 메모리를 받아오고 있다. IntArray(unsigned length) 생성자에서 메모리를 받아주고 있다.
{
int count = 0;
for (auto& element : list)
{
m_data[count] = element;
++count;
//m_data[count++] = element;
// C 스타일에 익숙한 사람들은 안에 넣어버리기도 한다.
// 요즘에는 컴파일러도 빨라지고 컴퓨터도 빨라지고 그래서 교수같은 경우는 사람이 실수하지 않도록 분리하는 편이다.
}
//for (unsigned count = 0; count < list.size(); ++count)
// m_data[count] = list[count]; // error
// count가 따로 되어있으니깐 번거로워보여서 옛날 프로그래머들은 이렇게 시도할 수 있다.overrun
// 그런데 std::initializer_list는 대괄호 operator를 제공하지 않는다. std::array나 std::vector에서는 사용할 수 있었는데 std::initializer_list는 제공해주지 않는다.
}
// 그래서 내부적으로 구현이되어있을 때 std::initializer_list 같은 경우는 iterator라는 것을 사용해서 for문을 돌리게 되어있는데
// for-each문은 내부적으로 std::initializer_list 안에 들어있는 iterator를 사용하는 구조이다. 이거는 std 라이브러리를 설명할 때 좀 더 자세하게 설명할 것이다.
// 편하게 사용하는 것은 좋은데 다른 사람들이 내가 구현할 것을 미리 구현해준 거기 때문에 어떻게 구현되어있나는 추가적으로 공부해야 된다.
// 어쨌든 공부하는 게 내가 다 구현하는 것보다는 훨씬 편하다. 이거는 뒤에 가서 강의 보면 그냥 이런 거였구나, 이렇게 쓰면 되는구나 하면 되는 거니깐 일단은 이렇게 번거롭더라도 count를 따로 붙여서 구현하는게 더 편하다 정도 생각하면 된다.
~IntArray()
{
delete[] this->m_data;
}
//TODO: overload operator =
// 사실 std::initializer_list을 이용해서 생성자를 구현하면 대입 연산자도 같이 오버로딩해주는게 좋다.
IntArray& operator = (const std::initializer_list<int>& list)
{
cout << "Assignment operator " << endl;
delete[] m_data;
m_length = list.size();
m_data = new int[m_length];
int count = 0;
for (auto& element : list)
{
m_data[count] = element;
++count;
}
return *this;
}
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()
{
int my_arr1[5] = { 1, 2, 3, 4, 5 };
int* my_arr2 = new int[5]{ 1, 2, 3, 4, 5 };
auto il = { 10, 20, 30 };
// #include <initializer_list>를 주석처리하면 에러가 난다.
//IntArray int_array = { 1, 2, 3, 4, 5 };
IntArray int_array{ 1, 2, 3, 4, 5 };
int_array = { 1, 2, 3, 4, 5, 6, 7 };
cout << int_array << endl;
return 0;
강민철
2022.10.02
buffer overrun만이 발생하는 것이 맞나요?
첨부하신 소스코드로는 아래와 같이 다수의 에러가 나오는 것 같아서요.
test.cc:9:20: warning: default member initializer for non-static data member is a C++11 extension [-Wc++11-extensions]
unsigned m_length = 0;
^
test.cc:10:14: warning: default member initializer for non-static data member is a C++11 extension [-Wc++11-extensions]
int* m_data = nullptr;
^
test.cc:19:22: error: no template named 'initializer_list' in namespace 'std'
IntArray(const std::initializer_list<int>& list)
~~~~~^
test.cc:34:35: error: no template named 'initializer_list' in namespace 'std'
IntArray& operator = (const std::initializer_list<int>& list)
~~~~~^
test.cc:23:8: warning: 'auto' type specifier is a C++11 extension [-Wc++11-extensions]
for (auto& element : list)
^
test.cc:23:22: warning: range-based for loop is a C++11 extension [-Wc++11-extensions]
for (auto& element : list)
^
test.cc:44:8: warning: 'auto' type specifier is a C++11 extension [-Wc++11-extensions]
for (auto& element : list)
^
test.cc:44:22: warning: range-based for loop is a C++11 extension [-Wc++11-extensions]
for (auto& element : list)
^
test.cc:66:27: error: expected ';' at end of declaration
int* my_arr2 = new int[5]{ 1, 2, 3, 4, 5 };
^
;
test.cc:68:2: warning: 'auto' type specifier is a C++11 extension [-Wc++11-extensions]
auto il = { 10, 20, 30 };
^
test.cc:68:12: error: cannot deduce type of initializer list because std::initializer_list was not found; include <initializer_list>
auto il = { 10, 20, 30 };
^
test.cc:72:11: error: no matching constructor for initialization of 'IntArray'
IntArray int_array{ 1, 2, 3, 4, 5 };
^
test.cc:13:2: note: candidate constructor not viable: requires single argument 'length', but no arguments were provided
IntArray(unsigned length)
^
test.cc:6:7: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided
class IntArray
^
test.cc:72:20: error: expected ';' at end of declaration
IntArray int_array{ 1, 2, 3, 4, 5 };
^
;
test.cc:73:14: error: expected expression
int_array = { 1, 2, 3, 4, 5, 6, 7 };
^
7 warnings and 7 errors generated.
thd2tn
질문자2022.10.04
// 기본 자료형으로 array를 만들 때는 initializer_list를 이용해서 값을 편하게 초기화할 수가 있었다.
// 이번에는 class 같은 사용자 정의 자료형에서 생성자나 대입 연산자를 만들 때 편하게 사용할 수 있는 std::initilalizer_list 사용법에 대해서 알아본다.
#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())
// 다른 생성자를 호출해서 메모리를 받아오고 있다. IntArray(unsigned length) 생성자에서 메모리를 받아주고 있다.
{
int count = 0;
for (auto& element : list)
{
m_data[count] = element;
++count;
//m_data[count++] = element;
// C 스타일에 익숙한 사람들은 안에 넣어버리기도 한다.
// 요즘에는 컴파일러도 빨라지고 컴퓨터도 빨라지고 그래서 교수같은 경우는 사람이 실수하지 않도록 분리하는 편이다.
}
//for (unsigned count = 0; count < list.size(); ++count)
// m_data[count] = list[count]; // error
// count가 따로 되어있으니깐 번거로워보여서 옛날 프로그래머들은 이렇게 시도할 수 있다.overrun
// 그런데 std::initializer_list는 대괄호 operator를 제공하지 않는다. std::array나 std::vector에서는 사용할 수 있었는데 std::initializer_list는 제공해주지 않는다.
}
// 그래서 내부적으로 구현이되어있을 때 std::initializer_list 같은 경우는 iterator라는 것을 사용해서 for문을 돌리게 되어있는데
// for-each문은 내부적으로 std::initializer_list 안에 들어있는 iterator를 사용하는 구조이다. 이거는 std 라이브러리를 설명할 때 좀 더 자세하게 설명할 것이다.
// 편하게 사용하는 것은 좋은데 다른 사람들이 내가 구현할 것을 미리 구현해준 거기 때문에 어떻게 구현되어있나는 추가적으로 공부해야 된다.
// 어쨌든 공부하는 게 내가 다 구현하는 것보다는 훨씬 편하다. 이거는 뒤에 가서 강의 보면 그냥 이런 거였구나, 이렇게 쓰면 되는구나 하면 되는 거니깐 일단은 이렇게 번거롭더라도 count를 따로 붙여서 구현하는게 더 편하다 정도 생각하면 된다.
~IntArray()
{
delete[] this->m_data;
}
//TODO: overload operator =
// 사실 std::initializer_list을 이용해서 생성자를 구현하면 대입 연산자도 같이 오버로딩해주는게 좋다.
IntArray& operator = (const std::initializer_list<int>& list)
{
cout << "Assignment operator " << endl;
delete[] m_data;
m_length = list.size();
m_data = new int[m_length];
int count = 0;
for (auto& element : list)
{
m_data[count] = element;
++count;
}
return *this;
}
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()
{
int my_arr1[5] = { 1, 2, 3, 4, 5 };
int* my_arr2 = new int[5]{ 1, 2, 3, 4, 5 };
auto il = { 10, 20, 30 };
// #include <initializer_list>를 주석처리하면 에러가 난다.
//IntArray int_array = { 1, 2, 3, 4, 5 };
IntArray int_array{ 1, 2, 3, 4, 5 };
int_array = { 1, 2, 3, 4, 5, 6, 7 };
cout << int_array << endl;
return 0;
}
return 0; 밑에 } 하나가 빠져있었네요 죄송합니다...
답변 1