인프런 커뮤니티 질문&답변

DveloperY0115님의 프로필 이미지
DveloperY0115

작성한 질문수

홍정모의 따라하며 배우는 C++

8.11 정적 멤버 함수

[16:30] Inner class를 이용하여 정적 멤버 변수를 초기화하는 과정에 대한 질문입니다.

작성

·

339

0

안녕하세요 교수님,

이번 겨울 교수님 덕분에 C++ 공부 즐겁게 하고 있는 학생입니다.

다름이 아니오라 제가 이 코드를 실행하다가 막히는 부분이 있어서 질문드립니다.

우선 실행 환경은

- macOS Catalina

- CLion / Clang 

입니다.

VS 위주로 수업이 진행되고, 이외의 플랫폼과 툴에 대해서는 답변이 어려울 수 있다는 말씀을 소개 페이지에 하셨지만 혹여나 제가 놓치고 있는 부분이 있을까 해서 질문 드립니다.

< 수정 >

main 함수 위쪽의

int Something::s_value = 1234; 로 변수의 값을 초기화 해주지 않은 걸 뒤늦게 발견했습니다. 

_init 이라는 내부 클래스를 만들고, Something의 멤버 변수(?)로 s_initializer 라는 인스턴스를 생성한 이유가 

이 인스턴스가 생성되면서 생성자가 호출 -> 생성자가 s_value를 9876이라는 값으로 초기화

인 것 같습니다만, s_initializer 호출 전에 s_value를 초기화시키지 않으면 아래의 오류가 발생하는 이유가 무엇인가요? (너무 질문이 길어져 죄송합니다...)

#include <iostream>

using namespace std;

class Something
{
public:
    class _init // inner class
    {
    public:
        _init() // constructor
        {
            s_value = 9876;
        }
    };

private:
    static int s_value;
    int m_value;
    static _init s_initializer;

public:
    Something()   // constructor
        : m_value(123)
    {}

    // static member function
    static int getValue()
    {
        /*
         * in static member function, you CANNOT use 'this pointer'
         * since both static member variable & function are independent
         * to the instances constructed using the class definition.
        */
        return s_value;
    }
};

// THIS IS NOT WORKING!!
Something::_init Something::s_initializer;

int main()
{
    Something st1;

    // cout << st1.getValue() << endl;
    /* fptr -> temp
     * and the function temp NEEDS 'this' pointer as its input.
     */


    /* In contrast,
     * static member functions are independent to the instances,
     * since it has its own address on memory so we don't need to
     * pass the pointer of instance('this') to it.
     */
    
    int (*fptr2)() = &Something::getValue;

    cout << (*fptr2)() << endl;
     

    return 0;
}

위에 첨부해드린 코드를 실행시키면 다음과 같은 에러를 볼 수 있습니다.

< 에러 메시지 >

Undefined symbols for architecture x86_64:

  "Something::s_value", referenced from:

      Something::getValue() in main_8_11.cpp.o

      Something::_init::_init() in main_8_11.cpp.o

ld: symbol(s) not found for architecture x86_64

clang: error: linker command failed with exit code 1 (use -v to see invocation)getValue() 라는 정적 멤버 함수에 의해 정적 멤버 변수 s_value가 참조되는 과정에서, 이 변수를 컴파일러가 찾을 수 없다는 내용인 것 같습니다.(제가 생각한 게 맞나요?)

교수님의 강의 코드와 요점 정리를 해주신 분 블로그의 코드까지 참고해서 작성했는데도 오류가 사라지지 않아서 이렇게 질문을 드립니다. 

추가적으로 문제 상황을 설명드리는데 있어 도움이 될까 싶어 한 가지 덧붙입니다:

Something::_init Something::s_initializer;  (main 함수 위)

에서 s_initializer 아래 노란줄이 표시되는데, 커서를 갖다대면 이런 메시지가 나옵니다.

Clang-Tidy: Initialization of 's_initializer' with static storage duration may throw an exception that cannot be caught 

교수님의 친절한 설명 덕분에 처음 배울 때엔 어렵게만 느껴졌던 참조자와 포인터 개념을 잡고 여기까지 올 수 있었습니다. 긴 질문 읽어주셔서 감사드립니다!

답변 2

3

홍정모님의 프로필 이미지
홍정모
지식공유자

static member variable은 별도로 초기화를 안해주면 메모리 배정이 안되어서 그런 문제가 생기는 것으로 기억합니다. 아래 링크 보시면 "implementation-defined manner" 라는 표현이 있는 것으로 봐서 OS나 컴파일러에 따라 달라질 수도 있으니 참고하세요.

https://stackoverflow.com/questions/3270427/when-is-memory-allotted-to-static-variables-in-c

0

DveloperY0115님의 프로필 이미지
DveloperY0115
질문자

읽어보니,

소스 코드에서 초기화가 되지 않은 static variable들은 BSS라고 하는 최하단의 메모리 영역으로 배정이 된다는 내용이고, 컴파일러마다 이런 할당을 처리하는 방식이 다르다는 것 같습니다.

이건 이후에 컴퓨터 시스템이나 OS같이 보다 근본적인 과목을 공부하면서 다시 살펴볼 필요가 있는 문제인 듯 싶네요.

덕분에 많은 것을 알아갑니다. 앞으로도 강의 열심히 듣겠습니다.

답변 감사합니다 :)

DveloperY0115님의 프로필 이미지
DveloperY0115

작성한 질문수

질문하기