월 24,200원
5개월 할부 시다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결홍정모의 따라하며 배우는 C++
Reference
조금 멍청한 질문이긴 한데 예전 수업에서 교수님께서int *ptr 과 int* ptr은 다른 것이라고 설명해주셨는데요.그럼 int &ref 와 int& ref도 다른 것인가요? 다르다면 혹시 어떤 점에서 다른 것인가요?
- 미해결홍정모의 따라하며 배우는 C++
2차원 배열 구성
const int num_rows{3}, num_columns{5}; int array[num_rows][num_columns] = { {1,2,3,4,5}, {6,7,8,9,10}, {11,12,13,14,15} };이렇게 행렬의 열과 행을 const로 상수 처리를 해버리면 컴파일에러가 발생하지 않는데 이"const"라는 키워드를 빼버리면 열과 행의 수가 변함으로 인해 메모리 공간을 할당을 못해서 컴파일 에러가 발생하는 건가요?
- 미해결홍정모의 따라하며 배우는 C++
포인터 자체의 주소 vs 포인터가 가리키는 주소
#include <iostream> using namespace std; int main() { int array[5] = { 1, 2, 3, 4, 5 }; int *ptr = array; // ptr 자체의 주소는 다름, 그러나 array의 첫번째 요소를 가리킴! cout << "ptr: " << ptr << endl; // 포인터가 가리키는 주소 == array 첫번째 요소 주소 cout << "&ptr: " << &ptr << endl; // ptr 자체의 주소 (array랑 다름) cout << "array: " << array << endl; cout << "sizeof(ptr): " << sizeof(ptr) << endl; // pointer 자체의 사이즈 cout << "sizeof(ptr): " << sizeof(&ptr) << endl; // 마찬가지 return 0; } 제 질문은ptr을 출력했을때는 포인터가 가리키는 주소, 즉 array의 주소를 반환하면서,왜 sizeof(ptr)에서는 &ptr을 하지 않았는데도 pointer 자체의 주소에 대한 size를 반환하나요?? 앞선 논리처럼 array 첫번째 요소,[0]에 대한 size를 반환해야하는 것 아닌가요? 감사합니다.
- 미해결홍정모의 따라하며 배우는 C++
IntArray 클래스 변수인 int_array의 소멸자가 왜 호출되는건가요?
#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]; } // initializer_list have not support [ ] operator. 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; cout < list.size(); ++count) // m_data[count] = list[count]; // error } ~IntArray() { delete[] this->m_data; } // TODO : overload operator = /*IntArray& operator = (const IntArray& arr) { if (this == &arr) return *this; delete[] m_data; m_length = arr.m_length; if (arr.m_data != nullptr) { m_data = new int[m_length]; for (unsigned i = 0; i < m_length; ++i) m_data[i] = arr.m_data[i]; } else m_data = nullptr; 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 }; IntArray int_array{ 1,2,3,4,5 }; cout << int_array << endl; int_array = il; cout << int_array << endl; return 0; }질문글이 좀 지저분해서 먼저 죄송합니다. 대입 연산자 오버로딩을 하지 않을 경우에, int_array = il; 대입 연산에서 에러가 나길래, 디버그를 해보니까 int_array 의 소멸자가 호출되어서 메모리공간이 그대로 없어지더라고요..그런데 제 개념상으로는 int_array 변수가 main 함수의 local 변수인데, 아직 프로그램이 끝나지않았는데도 왜 소멸자가 호출되는건가요?
- 미해결홍정모의 따라하며 배우는 C++
extern 전역변수 주소값
header 파일에서 전역상수를 미리 초기화하면 헤더를 부를때마다 다른 주소값이 할당된다고 하셨습니다. 그래서 cpp 파일에서 초기화를 따로 해주었습니다.그런데 cpp 파일에서 전역변수를 미리 초기화하면, 모든 다른 파일들에서 동일한 주소값이 할당되던데, 제가 맞을까요? 테스트로 돌려본 코드 첨부합니다. #include <iostream> extern char x; // 이미 extern 에서 초기화됐으면 다시 초기화 x // 아직 초기화 안했으면 여기서 초기화 -> 그럼 다른 파일에서 초기화 안돼!!!!!!!!!!!!!!!! extern void test(); int main() { x = 'm'; // extern에서 초기화 됐어도 변경 가능!!! std::cout << ::x << "\n"; std::cout << x << " " << static_cast<void*>(&x) << "\n"; // 변경 된 것 확인할 수 있음 test(); // 여기서도 변경 return 0; }extern char x = 'e';#include <iostream> extern char x; void test() { x = 't'; std::cout << x << " " << static_cast<void*>(&x) << "\n"; }물론 extern 변수를 선언만 한 후, main 함수가 있는 cpp 파일에서 초기화를 하더라도 마찬가지입니다.#include <iostream> extern void test(); extern char h = 'h'; int main() { h = 'u'; std::cout << ::h << " " << static_cast<void*>(&h) << "\n"; test(); return 0; }extern char h;#include <iostream> extern char h; void test() { h = 'j'; std::cout << ::h << " " << static_cast<void*>(&h) << "\n"; }감사합니다.
- 미해결홍정모의 따라하며 배우는 C++
개념이 헷갈려서 질문드립니다 (6.7a 널포인터)
포인터 자체가 가지고 있는 주소와포인터가 가리키는 변수의 주소랑 다른 개념이지 않나요? 예를 들어double d=123.4;double *ptr=&d;이면&ptr은 포인터 자체가 가지는 주소이고&(*ptr)은 포인터가 가리키는 변수의 주소인데이 값이 다르지 않나요? 이 말이 맞다면포인터 변수는 포인터 자체의 주소와 포인터가 가리키는 변수의 주소 둘 다 가지고 있는 건가요?너무 헷갈려서 질문드립니다 ..
- 미해결홍정모의 따라하며 배우는 C++
transform_reduced 의 결과값이 틀립니다.
아무리 봐도 코드 오류가 잘 안보이네요,어느부분이 잘못되었는지 짚어주실수 있을까요?#include <iostream> #include <thread> #include <mutex> #include <utility> #include <vector> #include <atomic> #include <chrono> #include <numeric> #include <random> #include <execution> #include <future> using namespace std; auto dotProductNaive(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]; return sum; } mutex mtx; auto dotProductLock(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) { std::scoped_lock lock(mtx); //c++17 sum += v0[i] * v1[i]; } return sum; } auto dotProductAtomic(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]; } } auto dotProductFuture(const vector<int>& v0, const vector<int>& v1, const unsigned i_start, const unsigned i_end) { int sum = 0; for(unsigned i=i_start; i<i_end; ++i) { sum += v0[i] * v1[i]; } return sum; } int main() { const long long n_data = 100'000'000; const unsigned n_threads = 4; //init 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);//unsigned long long const chrono::duration<double> dur = chrono::steady_clock::now() - sta; cout << dur.count() << endl; cout << sum << endl; cout << endl; } // cout << "Naive" << endl; // { // const auto sta = std::chrono::steady_clock::now(); // std::vector<thread> threads; // threads.resize(n_threads); // const unsigned n_per_thread = n_data / n_threads; // unsigned long long sum = 0; // for(unsigned t = 0; t < n_threads; ++t) // { // threads[t] = std::thread(dotProductNaive, std::ref(v0), // std::ref(v1), t*n_per_thread, (t+1)*n_per_thread, std::ref(sum)); // } // for(unsigned t = 0; t < n_threads; ++t) // threads[t].join(); // const auto dur = std::chrono::steady_clock::now() - sta; // cout << dur.count() << endl; // cout << sum << endl; // cout << endl; // } // cout << "Lock Guard" << endl; // { // const auto sta = std::chrono::steady_clock::now(); // unsigned long long sum = 0; // std::vector<thread> threads; // threads.resize(n_threads); // const unsigned n_per_thread = n_data / n_threads; // 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)); // } // for(unsigned t = 0; t < n_threads; ++t) // threads[t].join(); // const chrono::duration<double> dur = std::chrono::steady_clock::now() - sta; // cout << dur.count() << endl; // cout << sum << endl; // cout << endl; // } // cout << "Atomic" << endl; // { // const auto sta = std::chrono::steady_clock::now(); // atomic<unsigned long long> sum = 0; // std::vector<thread> threads; // threads.resize(n_threads); // const unsigned n_per_thread = n_data / n_threads; // for(unsigned t = 0; t < n_threads; ++t) // { // threads[t] = std::thread(dotProductAtomic, std::ref(v0), // std::ref(v1), t*n_per_thread, (t+1)*n_per_thread, std::ref(sum)); // } // 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 << "Future" << endl; // { // const auto sta = chrono::steady_clock::now(); // unsigned long long sum = 0; // vector<std::future<int>> futures; // futures.resize(n_threads); // const unsigned n_per_threads = n_data / n_threads; // for(unsigned t=0; t<n_threads; ++t) // { // futures[t] = std::async(dotProductFuture, std::ref(v0), std::ref(v1), // t*n_per_threads, (t+1)*n_per_threads); // } // for(unsigned t=0; t<n_threads; ++t) // sum += futures[t].get(); // const chrono::duration<double> dur = chrono::steady_clock::now() - sta; // cout << dur.count() << endl; // cout << sum << endl; // cout << endl; // } cout << "std::transform_reduce" << endl; { const auto sta = chrono::steady_clock::now(); const auto sum = std::transform_reduce(std::execution::par, 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; } return 0; }
- 미해결홍정모의 따라하며 배우는 C++
Iterator를 사용하는 이유가 무엇인가요?
제가 생각해본 바로는, 추후 코드의 리팩토링 과정을 더 편하게 만들기 위해(?)같습니다. 많은 STL 의 컨테이너가 동일한 용법을 갖고 있으면 편할테니까요. 혹시 다른 이유가 더 있을까요?
- 해결됨홍정모의 따라하며 배우는 C++
lock guard를 사용한 쓰레드 연산결과가 inner_product 함수를 사용한 결과와 다릅니다.
오타가 없는 것 같은데 무슨 이유로 다른 값이 나오는지 알수가 없네요. 도움부탁드립니다.아래는 코드 전문입니다.#include <iostream> #include <thread> #include <mutex> #include <utility> #include <future> #include <vector> #include <atomic> #include <chrono> #include <numeric> #include <random> #include <execution> using namespace std; auto dotProductFuture(const vector<int>& v0, const vector<int>& v1, const unsigned i_start, const unsigned i_end) { int sum = 0; for(unsigned i = i_start; i < i_end; ++i) { sum += v0[i] * v1[i]; } return sum; } auto dotProductNaive(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]; return sum; } mutex mtx; auto dotProductLock(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) { std::scoped_lock lock(mtx); //c++17 sum += v0[i] * v1[i]; } } int main() { const long long n_data = 100'000'000; const unsigned n_threads = 4; //init 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);//unsigned long long const chrono::duration<double> dur = chrono::steady_clock::now() - sta; cout << dur.count() << endl; cout << sum << endl; cout << endl; } cout << "Naive" << endl; { const auto sta = std::chrono::steady_clock::now(); std::vector<thread> threads; threads.resize(n_threads); const unsigned n_per_thread = n_data / n_threads; unsigned long long sum = 0; for(unsigned t = 0; t < n_threads; ++t) { threads[t] = std::thread(dotProductNaive, std::ref(v0), std::ref(v1), t*n_per_thread, (t+1)*n_per_thread, std::ref(sum)); } for(unsigned t = 0; t < n_threads; ++t) threads[t].join(); const auto dur = std::chrono::steady_clock::now() - sta; cout << dur.count() << endl; cout << sum << endl; cout << endl; } cout << "Lock Guard" << endl; { const auto sta = std::chrono::steady_clock::now(); unsigned long long sum = 0; std::vector<thread> threads; threads.resize(n_threads); const unsigned n_per_thread = n_data / n_threads; 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)); } // for(unsigned t = 0; t < n_threads; ++t) // threads[t].join(); const chrono::duration<double> dur = std::chrono::steady_clock::now() - sta; cout << dur.count() << endl; cout << sum << endl; cout << endl; } return 0; }
- 미해결홍정모의 따라하며 배우는 C++
3.6강의 16:49
if(x==1 && y++==2)에서++가 ==보다 우선순위가 높아y가 3이되고 2랑 같지않게되어서False이므로 중괄호안에 문장이 실행되지 않아야하는거아닌가요?제가 안에 문장넣엇는데 실행이되어서 헷갈리네요..
- 미해결홍정모의 따라하며 배우는 C++
강의 12.9 - 8:59 - std::vector에서 reference wrapper와 pointer 의 성능적인 차이
vector<Base*> vec;for(auto& el : vec)el->print();vector<reference_wrapper<Base>> vec;for(auto& el : vec)el.get().print();레퍼런스가 포인터보다 빠르지만 위에서는 get() 함수를 호출하니까 함수호출하면 스택프레임 전개되는데이러면 오히려 오버헤드가 더 커지는것 아닌가요?궁금해서 질문 올립니다.
- 해결됨홍정모의 따라하며 배우는 C++
async1의 start출력의 endl가 동작하지 않습니다
안녕하세요,분명 async1 start 출력 시 endl을 해주었는데도 줄바꿈 적용이 되지 않는 이유를 잘 모르겠습니다.설명 부탁드려도 될까요?
- 미해결홍정모의 따라하며 배우는 C++
seekg 질문입니다.
안녕하세요, 초반 seekg로 abcd.....z 저장된 txt읽는 코드를 동일하게 실행하였는데요,두번째 seekg 로 읽어올때 l 이 아닌 m을 읽어옵니다.원인이 무엇일까요?
- 미해결홍정모의 따라하며 배우는 C++
20.6 외부 라이브러리(Nano GUI) 설치후 빌드시 에러 발생 질문드려요
안녕하세요 이제 막 20.6장까지 들은 수강생입니다.20챕터의 경우 안되는 게 좀 있습니다.교수님 말씀대로 NanoGUI를 gitCMD를 통해 git clone --recursive 를 입력하여 로컬 Git폴더에 설치했습니다. 이후 CMAKE를 통해 NanoGUI가 있는 폴더를 경로지정하고 build 폴더를 만들어 진행하였습니다.그리고 CMAKE를 통해 해당 솔루션을 열고 Example2에 대해서 build를 실행할 시 자꾸 Error가 발생하여 failed가 발생합니다. 아무래도 header file일부를 읽어오지 못하는 것 같은데 가이드 부탁드립니다.경로를 찾아보려고 했는데 잘 안 찾아 지네요.그리고 추가로 전 강의(20.5)에서 VS의 다른 솔루션 두개를 동시에 컴파일 하시던데 방법이 있으면 가르쳐주시면 감사하겠습니다.
- 미해결홍정모의 따라하며 배우는 C++
21:30 a.length()
안녕하세요 교수님.교수님께서 강의 초반에 설명하실 때cout << "Hello, World" << endl;으로 쓰게 되면 내부적으로 "Hello, World"를 배열로 인식한다고 설명하셨고 'd' 뒤에 "끝이다"라는 문자가 생략되어서 배열이 13자리를 나타낸다고 하셨습니다. 21:30에서 "Hello, World" 를 string으로 입력받고 length함수를 이용해서 길이를 출력할 때는 12자리가 나왔는데 어떤 차이점이 있는 건가요?
- 미해결홍정모의 따라하며 배우는 C++
6.2 배열기초 2:09초 질문
- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! - 먼저 유사한 질문이 있었는지 검색해보세요. - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요. 안녕하세요 교수님교수님 강의를 보고 공부중인 학생입니다using namespace std;cout<<(int)&student_scores[2]<<endl;이 코드를 x code에서 컴파일을 하니까,Cast from pointer to smaller type 'int' loses information이런 식으로 나오면서 컴파일 에러가 발생합니다.이건 왜 이럴까요 그리고 번외적인 질문인데,왜 포인터의 주소값을 (int)로 캐스팅하면 이게 10진수로 바뀌나요? int라는 건 정수형을 나타내고, 이는 소수점을 표시하지 않는 거라고 생각하고, 진수 표현과는 관계가 없다는 생각이 들었습니다. 어떤 원리로 10진수로 바뀌는지 잘 모르겠습니다. 감사합니다.
- 해결됨홍정모의 따라하며 배우는 C++
(6.9) 포인터 주소를 찍어보는 구간에서 질문이 하나 생겼어요.
안녕하세요! 6.9강의에서 포인터 주소를 하나하나 찍어보는 구간에서 질문이 하나가 생겼습니다. #include <iostream> using namespace std; int main() { int i = 2; int *ptr_i = &i; double d = 3.14; double *ptr_d = &d; cout << "int형 포인터 ptr_i의 크기는 " << sizeof(ptr_i) << endl; cout << "ptr_i가 참조하는 변수 자체의 크기는 " << sizeof(*ptr_i) << endl; cout << "double형 포인터 ptr_d의 크기는 " << sizeof(ptr_d) << endl; cout << endl; cout << "------이하 ptr_i------" << endl; cout << "-1번째 : " << uintptr_t(ptr_i - 1) << endl; cout << "0번째 : " << uintptr_t(ptr_i) << endl; cout << "1번째 : " << uintptr_t(ptr_i + 1) << endl; cout << "2번째 : " << uintptr_t(ptr_i + 2) << endl; cout << endl; cout << "------이하 ptr_d------" << endl; cout << "-1번째 : " << uintptr_t(ptr_d - 1) << endl; cout << "0번째 : " << uintptr_t(ptr_d) << endl; cout << "1번째 : " << uintptr_t(ptr_d + 1) << endl; cout << "2번째 : " << uintptr_t(ptr_d + 2) << endl; } 결과값은 아래와 같이 나왔습니다.int형 포인터 ptr_i의 크기는 8ptr_i가 참조하는 변수 자체의 크기는 4double형 포인터 ptr_d의 크기는 8 ------이하 ptr_i-------1번째 : 61244665680번째 : 61244665721번째 : 61244665762번째 : 6124466580 ------이하 ptr_d-------1번째 : 61244665440번째 : 61244665521번째 : 61244665602번째 : 6124466568 포인터는 결국 '주소를 담고있는' 변수에 지나지 않잖아요?x64 환경에서 포인터의 크기는 어떤 자료형을 가리키던 상관없이 8바이트인데, 그렇다면 ptr_i에서 -1, +1 연산을 수행하면 결과값들이 8씩 차이가 나야하는게 맞지않나요? 제가 이해한 바로는 (물론 잘못 이해하고 있겠지만..) 포인터는 변수니까, 해당 포인터를 담고있는 또 다른 메모리 공간이 있을거란 생각이 들어서요.
- 미해결홍정모의 따라하며 배우는 C++
4.2 29분 48초
안녕하세요 교수님. extern 설명하실 때, 초보자 중에 include로 cpp파일을 가져오는 사람도 있다 그러셨는데, 혹시 이런 방식으로 가져오면 안 좋은 방식인 건가요? 혹시 그렇다면 이유가 있나요??
- 미해결홍정모의 따라하며 배우는 C++
[0.4.0] Clean Solution 후 Starting Without Debugging 시 자동으로 Build가 됩니다
Debug / Release 시Build 하는 안내창이 안나오고 바로 빌드 후 실행됩니다!Solution Clean 된 상태는 확인했습니다. 설정을 잘못 한걸까요 ㅠㅠ
- 미해결홍정모의 따라하며 배우는 C++
[0.4.0] VS 2022 에서 .ilk 파일이 Debug 폴더가 아닌 다른 폴더에 생성이됩니다
x64나 x83으로 빌드해도 다른 폴더에 .ilk 파일이 생성되는데 디렉토리를 변경해야할까요?