월 24,200원
5개월 할부 시다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결홍정모의 따라하며 배우는 C++
14.3 예외처리 클래스 상속과 객체 잘림에 대하여 질문 있습니다.
클래스는 Exception 클래스와 Exception 클래스를 상속받은 ArrayException 클래스를 선언 했습니다. 보시는 바와 같이 메인 함수에서 doSomething 함수를 호출합니다. 그리고 doSomething 함수 내부에서 my_array[100]에서 오버로딩한 [ ] 연산자 함수를 호출합니다. 그러면 오버로딩한 [ ] 연산자 함수에서 예외가 발생하여 throw에 의해서 ArrayException타입 객체를 기본 생성자를 호출하여 생성된 객체를 doSomething 함수의 내부에 있는 catch에 넘겨줍니다. 그렇게 되면 catch 옆에 (Exception& e) 처럼 값에 의한 전달이 아닌 참조에 의한 전달로 객체 자체를 넘겨줍니다. 그러면 Exception 클래스를 상속받은 ArrayException객체 자체를 e로 넘겨줍니다. 그리고나서 e.report()를 통해서 report 함수에 구현된 내용이 실행됩니다. 여기서 제가 궁금한것이 있습니다. 객체 잘림현상은 참조에 의한 전달이 아닌 값에 의한 전달에서 발생한다고 배웠는데 어째서인지 값에 의한 전달이 아닌 참조에 의한 전달로 객체 자체를 전달 했음에도 코드 실행 결과는 ArrayException클래스에서 구현한 report 함수의 내용이 아닌 Exception클래스에서 구현한 report 함수의 내용이 실행됩니다. 제가 알고있는 객체 잘림 현상에 대한 지식이 잘못된 것인지 아니면 예외 처리 클래스의 상속에 대해한 객체 잘림 현상이 특별한 경우인지 아니면 단순히 throw e와 throw의 차이인지 궁금합니다. 그다음에 메인 함수에서도 (Exception& e)에 값에의한 전달이 아닌 참조에 의한 전달로 객체 잘림이 발생한 ArrayException클래스 타입의 객체가 전달됩니다. 그리고 Exception 클래스에서 구현한 report 함수가 실행됩니다. 여기서는 doSomething 함수의 내부에서 객체 잘림 현상이 발생해서 Exception 클래스에서 구현한 report 함수가 실행된거라고는 이해가 됩니다. 그러면 왜 doSomething 함수 내부에서 객체 잘림이 발생한 것인지 궁금해서 질문 드립니다. 긴글 읽어주셔서 감사합니다.
- 미해결홍정모의 따라하며 배우는 C++
20.3 비쥬얼 스튜디오에서 깃헙 사용하기 질문있습니다.
교수님 비쥬얼 스튜디오에서 깃허브로 연결을 통해 비쥬얼 스튜디오에서 코드 작성 -> 깃허브에 공유 하는 방법을 알았습니다 반대로 깃허브 사이트에서 파일을 수정 -> 비쥬얼 스튜디오로 불러오기를 하고 싶습니다 구글링을 해봐도 교수님께서 제시해 주셨던 비쥬얼 스튜디오에서 코드 작성 -> 깃허브에 공유만 뜨거나 깃허브에서 파일을 내려받을 때는 CMD를 이용하는 방법 밖에 없었습니다 혹시 깃허브 사이트에서 파일을 수정 -> 비쥬얼 스튜디오로 불러오는 방법을 알 수 있을까요? 구글에 어떻게 검색하면 나올까요?
- 미해결홍정모의 따라하며 배우는 C++
3:00 질문 있습니다
영상에서 getCents를 사용해도 되고 std::vector vec(20); for (int i{ 0 }; i < 20; ++i) vec[i] = i; 이렇게 짜도 작동이 되긴 합니다. 하지만 교수님이 굳이 getCents()를 사용한 이유는 만약 Cents class안에 멤버 변수가 여러개 있다면 Cents 안에 m_cents의 직접접근이 안되기 때문에 getCents()로 호출한 것인가요?
- 미해결홍정모의 따라하며 배우는 C++
멀티쓰레딩 예제 실행시간 수정 질문
random_device seed; mt19937 engine(seed()); uniform_int_distribution <> uniformDist(1, 10); const auto sta2 = chrono::steady_clock::now(); //시간 재는중 for (long long i = 0; i < n_data; i++) { v0.push_back(uniformDist(engine)); v1.push_back(uniformDist(engine)); } const chrono::duration<double> dur2 = chrono::steady_clock::now() - sta2; //시간 재는 중 cout << dur2.count() << endl; 말씀하신 부분을 다음과 같이 해서 시간을 측정해보니 143.15초가 나왔습니다. for문을 이용해 vector에 값을 넣는 것에만 2~3분이 걸린 것입니다. 구글링 해본 결과 시간 복잡도 계산에 for문 기준으로 1억번 계산하는데 1초라는 내용을 알 수 있었습니다 for문안에 2억번 계산이 이루어지니까 산술적으로 2초가 걸립니다. 하지만 단순 값을 넣는 것이 아닌 완전 랜덤 숫자를 넣는 것이니까 2초보다는 조금 더 걸리겠지 라는 생각을 해봐도 시간이 지나치게 소요된다는 생각이 들었습니다. 교수님이 예제를 보여주실 때는 거의 순식간에 결과를 알 수 있었는데 이러한 차이가 어디서 오는건지 궁금합니다.
- 미해결홍정모의 따라하며 배우는 C++
멀티쓰레딩 예제 실행시간 재질문
말씀하신 코드는 다음과 같습니다 #include<iostream> #include<chrono> #include<mutex> #include<random> #include<thread> #include<utility> #include<vector> #include<atomic> #include<future> #include<numeric> //std::inner_product #include<execution> // parallel_execution using namespace std; mutex mtx; void dotProducNaive(const vector<int>& v0, const vector<int>& v1, const unsigned i_start, const unsigned i_end, unsigned long long& sum) { for (unsigned i = i_start; i < i_end ; i++) { sum += (v0[i] * v1[i]); //내적 구현 한 것 } } void dotProductLock(const vector<int>& v0, const vector<int>& v1, const unsigned i_start, const unsigned i_end, unsigned long long& sum) { //cout<<"Thread start"<<endl; for (unsigned i = i_start; i < i_end; i++) { std::scoped_lock lock(mtx); //c++17 sum += v0[i] * v1[i]; } } void dotProducAtomic(const vector<int>& v0, const vector<int>& v1, const unsigned i_start, const unsigned i_end, atomic<unsigned long long>& sum) { for (unsigned i = i_start; i < i_end ; i++) { sum += (v0[i] * v1[i]); //내적 구현 한 것 } } int main() { const long long n_data = 100'000'000; const unsigned n_threads = 8; //initialize vectors std::vector<int> v0, v1; v0.reserve(n_data); v1.reserve(n_data); random_device seed; mt19937 engine(seed()); uniform_int_distribution <> uniformDist(1, 10); for (long long i = 0; i < n_data; i++) { v0.push_back(uniformDist(engine)); v1.push_back(uniformDist(engine)); } cout << "std::inner_product" << endl; { const auto sta = chrono::steady_clock::now(); //시간 재는중 const auto sum = std::inner_product(v0.begin(), v0.end(), v1.begin(), 0ull); const chrono::duration<double> dur = chrono::steady_clock::now() - sta; //시간 재는 중 //계산한 시간 출력 cout << dur.count() << endl; cout << sum << endl; cout << endl; } cout << "Native" << endl; { const auto sta = chrono::steady_clock::now(); unsigned long long sum = 0; vector<thread> threads; threads.resize(n_threads); //쓰레드 마다 맡길 일의 양을 결정 const unsigned n_per_thread = n_data / n_threads; //assumes remainder=0 //쓰레드 할당 중 + 쓰레드에 값을 넣어주는 중 for (unsigned t = 0; t < n_threads; t++) { threads[t] = std::thread(dotProducNaive,std::ref(v0),std::ref(v1), t* n_per_thread, (t + 1)* n_per_thread, std::ref(sum)); } //join으로 기다리는 코드 for (unsigned t = 0; t < n_threads; t++) { threads[t].join(); } const chrono::duration<double> dur = chrono::steady_clock::now() - sta; cout << dur.count() << endl; cout << sum << endl; cout << endl; } cout << "Lock guard" << endl; { const auto sta = chrono::steady_clock::now(); unsigned long long sum = 0; vector<thread> threads; threads.resize(n_threads); //쓰레드 마다 맡길 일의 양을 결정 const unsigned n_per_thread = n_data / n_threads; //assumes remainder=0 //쓰레드 할당 중 + 쓰레드에 값을 넣어주는 중 for (unsigned t = 0; t < n_threads; t++) { threads[t] = std::thread(dotProductLock, std::ref(v0), std::ref(v1), t * n_per_thread, (t + 1) * n_per_thread, std::ref(sum)); } //join으로 기다리는 코드 for (unsigned t = 0; t < n_threads; t++) { threads[t].join(); } const chrono::duration<double> dur = chrono::steady_clock::now() - sta; cout << dur.count() << endl; cout << sum << endl; cout << endl; } cout << "atomic" << endl; { const auto sta = chrono::steady_clock::now(); atomic<unsigned long long> sum = 0; vector<thread> threads; threads.resize(n_threads); //쓰레드 마다 맡길 일의 양을 결정 const unsigned n_per_thread = n_data / n_threads; //assumes remainder=0 //쓰레드 할당 중 + 쓰레드에 값을 넣어주는 중 for (unsigned t = 0; t < n_threads; t++) { threads[t] = std::thread(dotProducAtomic, std::ref(v0), std::ref(v1), t * n_per_thread, (t + 1) * n_per_thread, std::ref(sum)); } //join으로 기다리는 코드 for (unsigned t = 0; t < n_threads; t++) { threads[t].join(); } const chrono::duration<double> dur = chrono::steady_clock::now() - sta; cout << dur.count() << endl; cout << sum << endl; cout << endl; } return 0; }
- 미해결홍정모의 따라하며 배우는 C++
레이스 컨디션 재질문
#include<iostream> #include<thread> #include<atomic> #include<mutex> #include<chrono> using namespace std; int main() { mutex mtx; int shared_momory(0); auto count_func = [&]() { for (int i = 0; i < 1000; i++) { //this_thread::sleep_for(chrono::milliseconds(1)); //std::scoped_lock lock(mtx); shared_momory++; } }; thread t1 = thread(count_func); thread t2 = thread(count_func); t1.join(); t2.join(); cout << "After" << endl; cout << shared_momory << endl; return 0; } 코드는 이렇습니다.
- 미해결홍정모의 따라하며 배우는 C++
19.6 멀티쓰레딩 예제 실행시간 질문
강의 11:08초에 예제를 실행시킬 때 교수님께서는 0.08초 이런식으로 1초가 걸리지 않는 시간에 내적 결과값이 나옵니다 하지만 제 컴퓨터의 경우에는(8코어 16쓰레드 입니다) 결과 값이 도출되기까지 4분이 소요됩니다. const unsigned n_threads = 4; 의 숫자를 키워봐도 시간이 빨라지지 않습니다. ctrl+F5로 프로그램을 실행 시킨 후 CPU 이용률을 살펴 봐도 평상시처럼 5%대라고 나와 있습니다. CPU가 벡터 예제를 전혀 연산하지 않는 것 같습니다. 또한 비주얼 스튜디오 속도 빠르게 하기로 구글링 하여 프로젝트 속성-> C/C++-> 일반에서 다중 프로세서 컴파일에 예라고 설정을 변경 한 후 프로젝트를 빌드하면 CPU 이용률이 100%까지 치솟으며 빌드는 1초도 안되서 끝납니다. 빌드는 1초도 안되어서 실행파일을 형성 시키는데 정작 실행파일 자체는 3~4분이 걸리는 이 현상, 뭐가 문제인가요?
- 미해결홍정모의 따라하며 배우는 C++
19.4 레이스 컨디션 질문
저 같은 경우는 // this_thread::sleep_for(chrono::milliseconds(1)); 이 쉬는 문장을 넣으면 정상적으로 나오고(atomic이나 기타 lock을 설정하지 않고도요) // this_thread::sleep_for(chrono::milliseconds(1)); 이 문장을 빼면 레이스 컨디션이 발생합니다. 보여주신 것과는 반대인데요. 혹시 왜 그런지 알 수 있을까요? CPU 차이인가요? 제 컴퓨터의 CPU는 AMD인데 교수님의 CPU는 인텔인 것에 차이가 있는건가요?
- 미해결홍정모의 따라하며 배우는 C++
19.3 멀티 쓰레딩 기초 질문있습니다
강의 19.3 16:06초에서 main을 실행시키면 프로세스 한 개가 생성된다. 이 프로세스 한 개가 CPU의 logical processor 1개를 사용한다고 하셨습니다. 1. 그렇다면 제가 프로세스를 16개 사용하면 CPU의 logical processor가 꽉차는건가요?(16개의 logical processor가 있다는 가정하에요) 2. 인터넷에 검색해 보면 CPU 성능 제원 중에 8코어 16쓰레드라는 표현이 있는데 logical processor가 쓰레드 인건가요? 3. 비주얼 스튜디오가 한 개의 프로세서를 만들고 작업 중에 3개의 자식 쓰레드를 만들었다면 비주얼 스튜디오 혼자서 CPU의 logical processor를 4개 차지하게 되는 건가요?
- 미해결홍정모의 따라하며 배우는 C++
질문
안녕하세요 IntList * list = new IntList; 이거에서 1번은 not ok 2번은 ok인데 1번은 제가 생각을 해보면 m_list[3]를 가리키는 반면에... 2번은 (*list)[3] 이게 2차원 배열에 접근하는 것 처럼 느껴지거든요 (*(list+0)+3) 이렇게 그래서 오히려 2번이 안되고 1번이 되는 느낌인데.. 이 부분 잘 이해가 안가네요 ㅠ
- 미해결홍정모의 따라하며 배우는 C++
질문
Digit& operator++ (int) { Digit temp(m_digit); ++(*this); //++m_digit; return temp; } 제가 알기로 *this는 객체 그 자체라고 알고 있는데 ++(*this) == ++m_digit 이 가능한가요? *this는 객체 그 자체이고 m_digit은 객체의 멤버변수인데요!
- 해결됨홍정모의 따라하며 배우는 C++
질문입니다. 연산자 오버로딩에 관해서
지금 제가 시험을 해봤는데 cout<<p1+p2+p3가 잘되거든요 근데 만들면서 생각한게 chaning이 되야하니까 operator+의 반환타입을 객체 그 자체로 해야한다고 생각했어요 왜냐면 체이닝을 해야한다고 생각을했거든요 그러니까 (p1+p2)에서 나온 Point의 객체+p3라고 생각을 해서 . 그런데 오히려 반환형에 &를 붙이면 lvalue~~하면서 오류가 나오고 없애면 잘 되네요. 조금 헷갈리는데 제가 생각한게 틀렸나요?
- 미해결홍정모의 따라하며 배우는 C++
15.3 이동 생성자와 이동 대입에서 타입에 대해 질문드립니다.
// AutoPtr.h template<class T> class AutoPtr { private: T * m_ptr; public: AutoPtr(T* ptr = nullptr) :m_ptr(ptr) { std::cout << "AutoPtr default constructor" << std::endl; } /////////////////////////////////////////////////////////////////////// // Resource.h class Resource { //private: public: int *m_data = nullptr; unsigned m_length = 0; public: Resource() { std::cout << "Resource default constructed" << std::endl; } Resource(unsigned length) { std::cout << "Resource length constructed" << std::endl; this->m_data = new int[length]; this->m_length = length; } /////////////////////////////////////////////////////////////////////// AutoPtr<Resource> res(new Resource(10000000)); <------main.cpp에 있는 코드 이 부분에서 어떻게 양변의 타입이 같은 것인지 이해가 가지 않습니다. 먼저 둘다 typeid().name() 을 해보니 7AutoPtrI8ResourceE 라고 나오니 타입이 같습니다. 그런데 제 머릿속으로 동적 할당을 이해하기로는 int *p(new int(10)); 같이 좌변 = 동적할당을 할 메모리의 주소를 저장할 '포인터' p 그 사이에 new 우변 = 동적할당을 할 메모리의 자료형(argument) 이렇게 이해하고 있습니다. 그런데 저는 AutoPtr<Resource> res(new Resource(10000000)); 는 좌변 = Resource형의 포인터 변수를 내부에 가지고 있는 클래스 AutoPtr 형 변수 res 그 사이에 new 우변 = int형 크기만큼 일렬로 10000000번 동적 할당한 메모리의 첫번째 주소를 가리키는 포인터 변수를 내부에 가지고 있는 클래스 Resource 라고 이해가 되는데요. 여기서 Resource를 하나의 자료형이라 보면 우변은 이해가 됩니다. 그런데 좌변은 '포인터' 가 아니라 '클래스' 라고 생각이 되어지는데 '포인터' 가 자리에 와야 한다고 생각이 들어서 어떻게 클래스가 들어와도 프로그램이 잘 작동이 되는지 이해가 가질 않습니다. 어떻게 이해하면 될까요?
- 미해결홍정모의 따라하며 배우는 C++
12.7 인터페이스 클래스에 관한 질문 있습니다.
인터페이스 클래스에서 마지막 부분이 이해가 잘 가지 않습니다. #include<iostream> #include<string> using namespace std; class IErrorLog { public: virtual bool reportError(const char* errorMessage) = 0; virtual ~IErrorLog() {}; }; class FileErrorLog : public IErrorLog { public: bool reportError(const char* errorMessage) override { cout << "Writing error to a file" << endl; return true; } }; class ConsoleErrorLog : public IErrorLog { public: bool reportError(const char* errorMessage) override { cout << "Priting error to a console" << endl; return true; } }; void doSomething(IErrorLog& log) { log.reportError("Runtime error!!"); } int main() { FileErrorLog file_log; ConsoleErrorLog console_log; file_log.reportError("ㅇㅇㄹ"); console_log.reportError("dfdf"); doSomething(file_log); doSomething(console_log); return 0; } file_log.reportError("ㅇㅇㄹ"); console_log.reportError("dfdf"); 과 doSomething(file_log); doSomething(console_log); 은 같은 기능을 할 수 있지 않습니까? 왜 doSomething 함수를 다시 정의하는것이 더 재활용성 있고 편한건가요? 함수 하나 더 정의했으니 코드량이 늘어난 것 아닌가요?
- 미해결홍정모의 따라하며 배우는 C++
12.2 다형성에 관한 질문있습니다.
수업을 듣다 다형성이 무엇인지 한 줄로 표현하면 무엇인가에 대한 궁금증이 생겼습니다. 구글을 찾아보면서 나름 한 줄로 줄인 결과는 다음과 같습니다 다형성은 무엇인가? 1. 같은 모양의 코드가 다른 행위를 하는 것을 나타내는 용어 C++에서는 다형성을 어떻게 구현하고 있는가? 2. C++에서는 virtual 키워드를 통한 오버라이딩을 통해 구현한다. 구현되는 장소는 서브 클래스(자식 클래스)이다. 슈퍼클래스(부모 클래스)를 상속받는 서브 클래스(자식 클래스)에서 다형성을 구현한다. 서브 클래스는 슈퍼 클래스의 virtual 멤버 함수를 같은 이름, 같은 반환 값, 같은 인자로 자신의 클래스 안에서 함수가 새로운 기능을 가지게 게 정의한다. 이렇게 정리 해보았습니다. 맞는 정리인지 여쭤보고 싶습니다.
- 미해결홍정모의 따라하며 배우는 C++
반환형질문
마마우스로 클릭해놔서 이해하시기 편하실텐데... 제가 볼 때는 셋 다 멤버변수 m_cents를 얻으려고 저러는건데 m_cents의 참조형 = m_cents의 값+m_cents의 값; 이게 이해가 잘 안갑니다 설명 부탁드려요~
- 미해결홍정모의 따라하며 배우는 C++
질문이 있습니다
1. 정적 멤버 변수는 class 내에서 초기화가 불가능한 이유를 아무리 찾아봐도 const를 붙여서 초기화 하는 방법 밖에 없던데 왜 그런지 이유가 궁금합니다. 2. 5:22초 에서 정적 변수는 main 함수 내에서 직접 접근 할 수 있는게 클래스 내부에서 정적 변수를 선언하고 프로그램을 실행할 때 객체가 생성되지 않아도 정적 변수는 메모리에 올라가 있기 떄문에 직접 접근 할 수 있는 건가요?
- 미해결홍정모의 따라하며 배우는 C++
int getCents() const 함수와 int& getCents()함수의 차이 질문 2
저도 강의 9-4 3분15초에 질문이 있습니다. int getCents() const //편의상 1번 함수 { return _cents; } int& getCents() //편의상 2번 함수 { return _cents; } vector<Cents> arr(20); //편의상 3번 for (int i = 0; i < 20; i++) { arr[i].getCents() = i; } 1,2번 함수와 3번의 관계에 대해 궁금합니다. 1번 멤버 함수는 없어도 3번이 작동하는데 문제가 생기지 않지만 2번 멤버 함수는 없으면 arr[i]에 밑줄이 생기면서 식이 수정할 수 있는 L-value여야 한다고 뜹니다. const가 문제 인 것 같아 2번 멤버 함수가 없는 채로 1번 함수에서 const를 제거해도 같은 오류가 생깁니다. L-value라 함은 주소에 접근 할 수 있는 변수라고 배웠습니다. 예를 들어 arr[0]에서 1번 함수에 접근해서 arr[0].m_cents를 return 받으면 되는 것 아닌가요 혹시 1번 함수의 경우 함수가 return 하면서 발생하는 익명객체의 m_cents를 arr[0].m_cents가 받기 때문에 문제가 발생하는 것인가요? 익명객체의 경우 금방 소멸해서 주소값을 알 수 없으니 말입니다. 반대로 2번의 경우 참조를 통해 arr[0]의 m_cents를 그대로 반환해 줘서 문제가 없는 건지 여쭤보고 싶습니다.
- 미해결홍정모의 따라하며 배우는 C++
9.2 입출력 연산자 4:17에서 질문
입출력 연산자에서 friend std::ostream& operator << (std::ostream& out, const Point& point) { out << point._x << " " <<point. _y << " " <<point. _z; return out; } return out을 해줘야 chaining을 할 수 있다고 말씀해 주셨습니다. return과 연속적인 사용하고는 무슨 관계가 있는 건가요>? return은 글자 그대로 값을 돌려주고 함수가 종료되는 것인데 return과 연속적인 사용사이의 관계가 궁금합니다.
- 미해결홍정모의 따라하며 배우는 C++
int getCents() const 함수와 int& getCents()함수의 차이
동전갯수를 합하는 코딩에서 int getCents() const 함수와 int& getCents()함수는 리턴값이 모두 m_cents로 같은데 무슨 차이가 있나요?