월 24,200원
5개월 할부 시다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결홍정모의 따라하며 배우는 C++
#include <algorithm>을 해주는 이유
16.3에서 설명해주신 코드에서#include <algorithm>을 해주지 않아도 min_element()나 sort(), reverse()가 정상적으로 작동이 되는데, 그 이유가 궁금합니다! #include <iostream> #include <vector> using namespace std; int main() { vector <int> container; for(int i = 0; i < 10; ++i) container.push_back(i); auto itr = min_element(container.begin(), container.end()); cout << *itr << endl; // 삽입 itr = find(container.begin(), container.end(), 3); container.insert(itr, 128); for (auto &e : container) cout << e << " "; cout << endl; // 정렬 sort(container.begin(), container.end()); for (auto &e : container) cout << e << " "; cout << endl; // reverse 정렬 reverse(container.begin(), container.end()); for (auto &e : container) cout << e << " "; cout << endl; return 0; }
- 해결됨홍정모의 따라하며 배우는 C++
call by reference 시 퍼포먼스에 관한 질문입니다.
과제로 내주신 것 중 std::thread와 std::promise를 사용하는 것을 먼저 해보고 divide and conquer를 std::thread를 이용해서 구현하는 것을 해봤는데, 궁금증이 생겨서 질문드렸습니다.강의 영상 막바지에 보여주셨던 std::async와 std::future를 사용했던 예제를 참고해서, 하나의 변수에 여러 스레드가 값을 누적시키는 것이 아닌 각자의 local sum에 값을 누적시킨 후 마지막에 모두 더하는 방식으로 구현해봤습니다. // TODO #1 : use divide and conquer strategy for std::thread cout << "thread" << endl; { const auto sta = chrono::steady_clock::now(); unsigned long long sum = 0; vector<std::thread> threads; vector<unsigned> sums; threads.resize(n_threads); sums.resize(n_threads); const unsigned n_per_thread = n_data / n_threads; for (unsigned t = 0; t < n_threads; t++) { threads[t] = std::thread(dotProductThread, std::ref(v0), std::ref(v1), t * n_per_thread, (t + 1) * n_per_thread, std::ref(sums[t])); } for (unsigned t = 0; t < n_threads; t++) { threads[t].join(); sum += sums[t]; } const chrono::duration<double> dur = chrono::steady_clock::now() - sta; cout << dur.count() << endl; cout << sum << endl; cout << endl; }그리고 처음에는 std::thread가 사용할 함수인 dotProductThread의 구현을 call by reference를 반환값처럼 사용하도록 아래와 같이 구현했습니다.auto dotProductThread(const vector<int>& v0, const vector<int>& v1, const unsigned i_start, const unsigned i_end, unsigned& local_sum) { for (unsigned i = i_start; i < i_end; i++) { local_sum += v0[i] * v1[i]; } }그런데 실행해봤더니 정답은 제대로 나오지만 속도가 제가 구현한 std::thread와 std::promise를 사용한 예제보다 훨씬 느렸고, 심지어 std::innerproduct보다도 느렸습니다.뭐가 문제일까 싶어 여러가지를 바꿔보다가 아래와 같이 dotProductThread함수에서 매번 레퍼런스에 값을 더하지 않고 변수를 하나 선언해 누적하다가 마지막에만 넘겨주도록 하였습니다.auto dotProductThread(const vector<int>& v0, const vector<int>& v1, const unsigned i_start, const unsigned i_end, unsigned& local_sum) { unsigned t = 0; for (unsigned i = i_start; i < i_end; i++) { t += v0[i] * v1[i]; } local_sum = t; }실행했더니 속도가 std::thread와 std::promise를 사용한 예제와 거의 비슷하게 나와주었습니다.call by reference로 전달된 참조에 너무 빈번하게 접근해도 퍼포먼스 저하가 일어난다고 봐도 될까요?그리고 시험삼아 출력문을 dotProductThread 내에 작성해봤더니 race condition은 일어나지 않는 것 같았습니다. 이런 경우 굳이 std::atomic이나 뮤텍스를 사용할 필요는 없나요? 또는 작업이 더욱 복잡해진다면 안정성을 위해 사용해줘야 하는 걸까요?(프로그래머가 미처 고려하지 못한 상황이라거나)
- 해결됨홍정모의 따라하며 배우는 C++
15.1 소유권 이동 관련 질문
15.1 강의에서 16분 20초 부근에AutoPtr(AutoPtr &a) { m_ptr = a.m_ptr; // 이 부분 a.m_ptr = nullptr; // 이 부분 } AutoPtr& operator = (AutoPtr &a) { if (&a == this) return *this; delete m_ptr; m_ptr = a.m_ptr; // 이 부분 a.m_ptr = nullptr; // 이 부분 return *this; }소유권 이동을 해주기 위해 AutoPtr 클래스에 위와 같이 복사생성자와 =연산자 오버로딩을 해준다고 하셨습니다.그런데 이 때, 제가 "이 부분"이라고 주석처리 해놓은 부분을 보면 같은 명령을 수행하도록 되어있습니다. 왜 이렇게 두 번 해주는지 궁금합니다. 복사생성자에서 해주는 것과 연산자 오버로딩에서 해주는 것. 둘의 차이는 무엇인가요? 그리고 =연산자 오버로딩에서 return *this를 하는 이유도 궁금합니다.
- 미해결홍정모의 따라하며 배우는 C++
const와 extern
안녕하세요const가 변수의 외부연결을 막는 것 같은 상황이 생기는 거 같아 이렇게 여쭤봅니다. 파일구조는 vars.cpp -> header.h -> main.cpp&test.cpp입니다.vars.cppheader.hmain.cpptest.cpp의도한대로 잘 작동하며 출력화면은 아래와 같습니다.그런데 여기서 vars.cpp에서 nmsp_a변수를 int에서 const int형으로 바꾸고,header.h에서도 nmsp_a를 extern int에서 extern const int형으로 바꾸고 돌려보면아래와 같이 오류가 발생합니다.차이점은 equipe namespace안의 int nmsp_a변수를 그냥 int에서 const int로 바꾼 것 뿐인데 충돌이 일어나는 것처럼 보입니다.const와의 어떠한 문제 때문인 것으로 추측되는데 vars.cpp의 namespace안의 nmsp_a변수에는 extern을 붙이지 않아왔고 nmsp_a를 가져다끌어 쓰는 header.h에서만 extern을 붙여줬는데 아래 사진과 같이vars.cpp의 nmsp_a 변수에 오류를 발생시키던 const를 붙이되 extern또한 추가로 붙여주면 정상출력을 합니다. const를 안 붙이는 상황에선,변수를 정의해두는 vars.cpp에서는 extern를 쓰지않고이를 가져오는 주체인 header.h에만 extern를 붙여도 정상작동했지만 const를 붙이는 상황에선,vars.cpp, header.h 두 곳 모두 각각 변수에 extern을 붙여줘야한다는 결론을 얻었습니다. 말이 좀 복잡한데 정리하자면왜 변수에 const가 없으면vars.cpp에는 extern을 안 붙여도 되고왜 변수에 const가 있으면vars.cpp에도 extern을 꼭 달아줘야하는지그런 차이가 왜 생기는지 궁금합니다. 감사합니다.
- 미해결홍정모의 따라하며 배우는 C++
setprecision 용법
안녕하세요.교수님께서 setprecision을 사용하실 때 cout << std::setprecision(~)... 로 사용하셨습니다.이전 제가 들은 설명으론 cout는 콘솔출력으로서 c의 printf처럼 내보낼 게 있을 때 쓰는 것으로 알고있는데무언가를 출력하지않고 그냥 셋팅에 가까운 역할을 수행하는데 왜 콘솔출력 cout를 앞에 붙여 쓰는지 그 의의를 모르겠습니다.그냥 단순한 문법인가요?19:25 부분입니다
- 미해결홍정모의 따라하며 배우는 C++
코드 오류 관련 질문드립니다.
#include <iostream> #include "a.cpp" using namespace std; static int g_a = 1; //void doSomething(); int main() { int a = 10; doSomething(); return 0; } #include <iostream> void doSomething() { using namespace std; cout << "Hello " << endl; }a.cpp가 아래와 같다고 할 때, 강의에서는 이렇게 코딩하는 경우는 거의 없지만 그래도 가능은 하다고 하셨는데, 실제로 컴파일해보니 오류가 발생합니다. 왜 오류가 나는지 모르겠습니다!
- 해결됨홍정모의 따라하며 배우는 C++
강의 내용과 object slicing에 대해 질문이 있습니다.
지금까지 들은 강의에서는 매개변수에 &가 있는 경우에는 call by reference로 동작하고, copy를 하지 않는 방식으로 알고 있었습니다. 그리고 call by value로 동작하는 경우에는 상황에 따라서 object slicing이 발생할 가능성이 있다고 이해했었습니다.그런데 강의에서 아래 코드처럼 &이 있는데 object slicing이 발생하신다고 하셔서 몹시 혼란스럽더라구요.catch(Exception& e) { e.report(); }그래서 다른 분들의 질답글과 C++ 표준(n3690을 참고했습니다)을 찾아봤습니다.Throwing an exception copy-initializes (8.5, 12.8) a temporary object, called the exception object. The temporary is an lvalue and is used to initialize the variable named in the matching handler (15.3). If the type of the exception object would be an incomplete type or a pointer to an incomplete type other than (possibly cv-qualified) void the program is ill-formed. Evaluating a throw-expression with an operand throws an exception; the type of the exception object is determined by removing any top-level cv-qualifiers from the static type of the operand and adjusting the type from “array of T” or “function returning T” to “pointer to T” or “pointer to function returning T,” respectively- C++ ISO n3690 15.1/3내용을 보니 throw를 하게 되면 exception object(예외 객체)라는 것을 copy-initialize하고, 해당 객체는 l-value이고 일치하는 handler에서 변수를 초기화하기 위해 사용된다고 되어 있었습니다.그리고 영상에서 rethrow 시 throw; 처럼 피연산자가 없는 경우 object slicing이 발생하지 않는다고만 나와서 설명이 좀 빈약한 것 같아 더 찾아봤습니다.A throw-expression with no operand rethrows the currently handled exception (15.3). The exception is reactivated with the existing exception object; no new exception object is created. The exception is no longer considered to be caught; therefore, the value of std::uncaught_exception() will again be true.- C++ ISO n3690 15.1/8throw;의 경우 새로운 exception object를 생성하지 않고, 기존 exception object로 다시 예외를 활성화시킨다고 나와있었습니다.좀 정확하게 확인하려고 예외 객체의 주소를 각 시점에 출력하도록 했습니다.class MyArray { private: int m_data[5]; public: int& operator [](const int& index) { if (index < 0 || 5 <= index) { ArrayException e; cout << &e << endl; throw e; } return m_data[index]; } }; void doSomething() { MyArray my_array; try { my_array[100]; } catch (Exception& e) { cout << "doSomething()" << endl; cout << &e << endl; e.report(); throw e; } } int main() { try { doSomething(); } catch (Exception& e) { cout << "main()" << endl; cout << &e << endl; e.report(); } return 0; }[] 연산자로 범위를 벗어난 인덱스에 접근했을 때 예외 객체를 생성하고doSomething() 함수의 catch() 내에서main() 함수의 catch() 내에서이렇게 확인했는데, 위에서 확인했던 내용대로 주소가 모두 달랐습니다. 그리고 doSomething() 에서 rethrow 를 throw;로 변경하니 2번과 3번의 출력 주소가 같았습니다.종합해보면 throw로 전달되는 객체의 복사 여부는 catch()의 &에 따라 달라지는 것이 아니고, throw에 피연산자가 생략되어 있냐 없냐로 달라지는 것 같더라구요. 그 마저도 throw; 처럼 작성하는 것은 rethrow할 때만 가능한 것 같았습니다.다음으로 그렇다면 왜 catch()에서 참조를 이용하는지 아래 링크를 참고했습니다.https://wiki.sei.cmu.edu/confluence/display/cplusplus/ERR61-CPP.+Catch+exceptions+by+lvalue+reference참고해보니 예외 클래스가 상속 관계를 가지는 경우, 예외 객체를 초기화하는 과정에서 object slicing이 발생할 수 있기에 &를 추가한다고 되어 있었습니다.실제로 주소 출력을 했던 테스트 코드에서 doSomething()에서는 throw;로 작성하더라도 main()의 catch()에서 &을 지우니 2번과 3번의 출력 주소가 달라졌습니다.그리고 생각을 해보니 throw는 expression이지 함수는 아니고, 더 찾아보니 'throwing by reference' 같은 개념은 존재하지도 않더라구요.결론적으로 함수에서와 throw 문에서의 &는 참조라는 같은 의미로 사용되지만, 함수의 매개변수에 사용하는 &는 call by reference로 작동하기 위한 것이고 catch()에서 사용하는 &는 object slicing을 피하기 위한 것이라고 이해하면 될까요?글이 조금 난잡할 수도 있는데, 읽어주셔서 감사합니다.
- 미해결홍정모의 따라하며 배우는 C++
피보나치 수열 문제
이렇게 만들었는데 평가해주실 수 있나요? 수정사항 부탁드려요,
- 해결됨홍정모의 따라하며 배우는 C++
링킹 에러 관련하여 제가 이해한 것이 맞는지 궁금합니다.
빌드를 하게 되면 .cpp 파일끼리 서로 알게 되는 것으로 알고 있었는데, 선언과 정의를 분리했다고 해서 이전의 내용과는 다르게 추가적인 작업을 해 줘야 하는 것이 이해가 잘 가지 않아 다른 분들 질답글도 찾아보고 제 나름대로 생각해 봤는데, 아래 내용이 맞는지 확인 부탁드립니다.빌드 시 각 .cpp 파일을 컴파일 하며 메모리를 잡고, 그 이후에 링킹을 진행한다. main에서 인스턴스 my_array에 대해 print()를 호출하려면 my_array 선언 시 템플릿 인자로 넘겨주었던 데이터 타입과 일치하는 print()의 body가 메모리에 잡혀있어야 한다.어떤 데이터 타입에 대한 print()를 메모리에 잡을지 알아야 하는 것이 관건이기에, 선언과 정의가 모두 헤더 파일에 위치한 경우에는 문제가 없다. 해당 헤더 파일을 include하는 .cpp파일을 컴파일하면 해당 .cpp 파일 내에서 템플릿 인자로 사용되는 데이터 타입에 대한 인스턴스가 메모리에 잡히기 때문이다.하지만 선언과 정의를 분리한 경우 print()의 body가 위치한 .cpp 파일과 템플릿 인자를 통해 클래스를 사용하는 main은 링킹이 되어야만 서로에 대하여 알 수 있는데, 정작 링킹 시점에서는 main 내에서 사용하는 특정 데이터 타입에 대한 멤버 함수의 메모리가 잡혀있지 않은 상태이므로 링킹 에러가 발생하게 된다.따라서 explicit instantiation으로 미리 특정 데이터 타입에 대한 print()의 메모리를 할당 받도록 하면 링킹 시점에서는 주어진 템플릿 인자에 맞는 함수가 메모리에 위치하게 되어 문제가 해결된다.이렇게 이해했는데 이게 맞는 걸까요...?
- 미해결홍정모의 따라하며 배우는 C++
코드 clone 문의
현재 따라배우는 c++ 수강중인데, 선생님이 작성하신 코드는 어디서 clone 할 수 있나요 ?선생님 github이나 질문 도우미분 github에는 없어서 여쭤봅니다.
- 미해결홍정모의 따라하며 배우는 C++
6.6 strcpy, strcat 함수 코딩
안녕하세요, 한번 strcpy와 strcat의 기능을 수행하는 함수를 작성해 보았습니다.일단 작동은 제대로 되는 지 확인이 되었고, 부족한 부분이 있다면 얼마든지 피드백 주시면 감사하겠습니다!void Strcpy(char* dest, char* source) { int count = 0; for (int i = 0; i < 50; i++) { if (source[i] == NULL) { break; } count++; } for (int i = 0; i < count + 1; i++) { dest[i] = source[i]; } } void Strcat(char* dest, char* source) { int count_d = 0; int count_s = 0; for (int i = 0; i < 50; i++) { if (source[i] == NULL) { break; } count_s++; } for (int i = 0; i < 50; i++) { if (dest[i] == NULL) { break; } count_d++; } for (int i = 0; i < count_s + 1; i++) { dest[i+count_d] = source[i]; } } int main(void) { using namespace std; char source[50] = "Copy this!"; char dest[50]; Strcpy(dest, source); Strcat(dest, source); cout << "This is source : " << source << endl; cout << "This is dest : " << dest << endl; return 0; }
- 해결됨홍정모의 따라하며 배우는 C++
9.11 8분쯤 질문
#include <iostream> #include <cassert> using namespace std; class MyString { 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() { delete[] m_data; } char* getString() { return m_data; } int getLength() { return m_length; } }; int main() { MyString hello("Hello"); cout << (int*)hello.m_data << endl; cout << &(hello.m_data) << endl; cout << hello.getString() << endl; { MyString copy = hello; cout << (int*)copy.m_data << endl; cout << &(copy.m_data) << endl; cout << copy.getString() << endl; } cout << hello.getString() << endl; return 0; } 여기에서 cout << (int*)hello.m_data << endl; 과 cout << &(hello.m_data) << endl; 의 값이 다르게 출력되는 이유가 뭔지 궁금합니다.int main() { char name[] = "jack jack"; cout << (int*)name << endl; cout << &name << endl; }이렇게 했을 때는 두 주소값이 같게 찍히는데, 위의 경우와 어떻게 다른지 궁금합니다. 그리고 main함수에서 scope를 빠져나오고, cout << hello.getString() << endl; 했을 때, 저는 Hello 라고 잘 출력이 되는데, 이건 컴파일러와 다른건가요? (강의 영상 8분 22초에서 보여지는 결과와 다르게 나옵니다.)
- 미해결홍정모의 따라하며 배우는 C++
함수와 변수에서 extern 키워드가 생략될때의 메커니즘 차이
안녕하세요, extern 키워드가 생략될때의 메커니즘이 함수와 변수에 차이가 있는 것 같은데 이해가 되지않아 질문드립니다. 우선 교수님께서 forward declaration 설명주실때,void doSomething(); 에서 앞에 extern 키워드가 생략된 것이라고, 변수도 똑같이 생략된것이라고 말씀주십니다. 하지만 제가 실험해본바로 변수는 좀 다른 것 같습니다.어떤 실험을 해봤냐면요,"Main.cpp""testGlobal.cpp"실행시키면 multiply definition 에러가 뜨는데요,Main.cpp 파일에서 g_testGlobal 을 선언할때 int로만 선언하는게 아닌 extern int로 선언하면 에러가 안뜹니다.만약 extern 키워드가 생략된 것이라는 교수님의 말씀이 맞다면, 왜 extern int g_testGlobal; 는 에러가 안뜨고 int g_testGlobal; 은 에러가 뜨는지 궁금합니다. 둘다 에러가 안떠야 extern 이 생략된게 맞지 않나요? 다음 실험도 봐보시면 좀 더 명확한데요,"Main.cpp""testGlobal.cpp" 파일에서이렇게 extern 키워드를 바꿔치기하면 또 빌드가 잘 됩니다.여기서는 하기 답변을 참고했을 때, 위 코드가 성공적으로 빌드되는 이유를 생각해봤는데요, https://www.inflearn.com/questions/102747/42-20-%EC%BD%94%EB%94%A9%EC%97%90-%EB%AC%B8%EC%A0%9C%EA%B0%80-%EC%97%86%EC%96%B4-%EB%B3%B4%EC%9D%B4%EB%8A%94%EB%8D%B0-%EB%B9%8C%EB%93%9C%EA%B0%80-%EC%95%88%EB%90%A9%EB%8B%88%EB%8B%A4 Main.cpp 에서 obj파일이 만들어질때 g_testGlobal 변수를 extern으로 선언했으므로 g_testGlobal 변수가 어딘가 저장되어있을거라는 정보를 컴파일러에게 건네주고, 그 값을 testGlobal.cpp 의 obj 파일이 링킹될때 건네 받아 사용하는것으로 이해했습니다.하지만 반대의 경우는 안되는 것이 이해가 가지 않습니다. 왜 두번째 경우에선 tetsGlobal.cpp에서 extern을 안써줘도 빌드가 되는지 모르겠습니다. 감사합니다.
- 미해결홍정모의 따라하며 배우는 C++
6.9 연습문제 의도대로 한게 맞는건가요..?
결과는 잘 나오는디..교수님 의도대로 한거인지를 모르겠어요.
- 미해결홍정모의 따라하며 배우는 C++
리턴 값으로 초기화 시 복사 생성자 호출이 안됩니다.
#include<iostream> #include<cassert> using namespace std; class Fraction { private: int m_numerator; int m_dominator; public: Fraction(int numerator, int dominator) :m_numerator(numerator), m_dominator(dominator) { assert(dominator != 0); } Fraction(const Fraction& fraction) :m_numerator(fraction.m_numerator) , m_dominator(fraction.m_dominator) { assert(fraction.m_dominator != 0); cout << "Copied" << endl; } friend std::ostream & operator << (std::ostream& out, const Fraction& fr) { out << fr.m_numerator << " / " << fr.m_dominator << endl; return out; } }; Fraction doSomething() { Fraction temp(1, 2); cout << &temp << endl; return temp; } int main() { //return값 복사 Fraction fr = doSomething(); cout << &fr << endl; return 0; }위 코드에서 복사 생성자를 호출하지 않는 이유는 뭘까요? 사용환경에 따라서 rvo를 시켜주는건가요??
- 해결됨홍정모의 따라하며 배우는 C++
9.12 강의 마지막에 내주신 숙제가 잘 이해가 안갑니다.
대입연산자를 오버로딩 해보라고 말씀하셨는데 대입연산자를 이용해서 이니셜라이저리스트로 클래스를 생성해보란 말씀이신가요? 근데 그건 이미 교수님이 강의 마지막에 되는걸 보여주신거 아닌가요?
- 미해결홍정모의 따라하며 배우는 C++
3.3 강의 후위 연산 질문
먼저 강의 정말 유익하게 잘 보았습니다.본론으로 들어가면 선생님께서는 전위 연산을 사용하였더니 4라는 결과가 나왔지만 후위 연산을 사용하니깐 결과값이 3이 나왔습니다.여기서 a는 2가 되는 것이 이해가 되지만 b는 왜 1이 되는지 의문이여서 질문글을 남깁니다.
- 해결됨홍정모의 따라하며 배우는 C++
다중 상속 시 부모 클래스 간 생성자 호출 순서가 궁금합니다.
단일 상속 시에는 member initializer list에서 부모 클래스의 생성자와 멤버 간의 순서를 바꾸어도 무조건 부모 클래스의 생성자가 먼저 호출되었었는데, 다중 상속시에는 어떤 부모 클래스의 생성자가 먼저 호출될 지 궁금해서 테스트를 해봤습니다. // USBDevice의 constructor USBDevice(long id) : m_id(id) { cout << "USB" << endl; } // ~~~ // NetworkDevice의 constructor NetworkDevice(long id) : m_id(id) { cout << "Network" << endl; }먼저 생성자의 호출 순서를 알 수 있게 간단하게 문자열을 출력하도록 수정하였습니다.class USBNetworkDevice : public USBDevice, public NetworkDevice { public: USBNetworkDevice(long usb_id, long net_id) : USBDevice(usb_id), NetworkDevice(net_id) { } };위 코드와 같은 수정하지 않은 상태에서는 USB가 먼저 출력되고 그 다음 Network가 출력되었습니다. member initializer list에서 순서를 바꾸어도 똑같았구요.class USBNetworkDevice : public NetworkDevice, public USBDevice { public: USBNetworkDevice(long usb_id, long net_id) : USBDevice(usb_id), NetworkDevice(net_id) { } };다음으로는 상속할 클래스를 나열할 때의 순서를 바꾸었더니 Network 가 먼저 출력되고 다음으로 USB가 출력되었습니다. 상속할 클래스를 나열한 순서에 따라서 생성자의 호출 순서가 바뀐다고 보면 될까요? 아 그리고 이런 생성자 호출 순서를 고려해야 하는 작업이 있나요? 객체지향적으로 설계한다면 생성자의 호출 순서에 따라 결과가 바뀌도록 설계하진 않을 것 같아서요.
- 미해결홍정모의 따라하며 배우는 C++
9.3 강의 보다가 궁금한 점
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() { Cents cents1(6); Cents cents2(0); cout << cents1 << endl; cout << cents2 << endl; cout << -cents(-10) << endl; cout << !cents1 << endl; cout << !cents2 << endl; return 0; } // 결과 (6) (0) (10) 0 1 이렇게 1~3번째와 4,5번째가 다른 이유가 궁금합니다.
- 해결됨홍정모의 따라하며 배우는 C++
if( 5 ) 자주 쓰나요?
안녕하세요, 좋은 강의 잘 듣고 있습니다.if (items_flag & opt1) 이런식으로 item1이 있는지 없는지 판단하는데,여기서 if() 안의 표현식이 0이 아닌 값으로 평가되면 true가 나온다는걸 이용하는건 알겠는데요,이 방식이 현업에서도 많이 쓰이나요?강의 초반에서도 교수님이 보는 이를 배려하는 코드, 가독성이 좋은 코드를 강조했는데, if() 안의 표현식이 0, 1, 2, 3, 4, 5 ... 등등 으로 평가되는 것보다 깔끔하게 0,1 혹은 true false 로만 평가되는게 가독성 측면에선 더 낫지 않나요?