Program Club

왜 std :: cout을 작성해야하고 std :: <<

proclub 2020. 11. 5. 19:48
반응형

왜 std :: cout을 작성해야하고 std :: <<


왜 다음 과 같은 코드 를 작성 std::cout하지 않고 작성해야합니까?std::<<

#include <iostream>

int main() {
    std::cout << "Hello, world!";
    return 0;
}

coutstd라이브러리에서 제공되며 <<일반적으로 비트 이동에 사용 되지 않습니까? 그렇다면 다른 의미로도 사용 ::되기 <<때문에 이전에도 범위 연산자를 작성하지 않아도되는 이유는 무엇입니까? 컴파일러는 이후 std::cout<<다른 것을 의미한다는 것을 어떻게 알 수 있습니까?


먼저 컴파일러는의 왼쪽과 오른쪽에있는 유형을 살펴 봅니다 <<. std::cout유형 std::ostream이고 문자열 리터럴은 15const char 유형 배열입니다 . 왼쪽은 클래스 유형이므로라는 함수를 검색합니다 operator<<. 문제는 어디로 보일까요?

이 이름 operator<<에 대한 조회는 함수 이름이와 같이 정규화되지 않았기 때문에 소위 비정규 조회 std::operator<<입니다. 함수 이름에 대한 규정되지 않은 조회는 인수 종속 조회를 호출합니다. 인수 종속 조회는 인수 유형과 관련된 클래스 및 네임 스페이스에서 검색합니다.

를 포함 <iostream>하면 서명의 무료 기능

template<typename traits>
std::basic_ostream<char, traits>& operator<<(std::basic_ostream<char, traits>&,
                                             const char*);

네임 스페이스에 선언되었습니다 std. 이 네임 스페이스는의 유형과 연결되어 std::cout있으므로이 함수를 찾을 수 있습니다.

std::ostream는의 typedef std::basic_ostream<char, std::char_traits<char>>뿐이며 15const char배열은 암시 적으로 a char const*(배열의 첫 번째 요소를 가리킴)로 변환 할 수 있습니다 . 따라서이 함수는 두 가지 인수 유형으로 호출 할 수 있습니다.

의 다른 오버로드가 operator<<있지만 위에서 언급 한 함수는 인수 유형과이 경우 선택한 유형에 가장 적합합니다.


인수 종속 조회의 간단한 예 :

namespace my_namespace
{
    struct X {};

    void find_me(X) {}
}

int main()
{
    my_namespace::X x;
    find_me(x);       // finds my_namespace::find_me because of the argument type
}

NB이 함수는 연산자이므로 실제 조회는 조금 더 복잡합니다. 첫 번째 인수의 범위 (클래스 유형 인 경우), 즉 멤버 함수에서 정규화 된 조회를 통해 조회됩니다. 또한 비 한정 조회가 수행되지만 모든 멤버 함수는 무시됩니다. 비정규 조회는 실제로 인수 종속 조회가 두 번째 단계 인 2 단계 절차와 같기 때문에 결과는 약간 다릅니다. 첫 번째 단계가 멤버 함수를 찾으면 두 번째 단계가 수행되지 않습니다. 즉, 인수 종속 조회가 사용 되지 않습니다 .

비교:

namespace my_namespace
{
    struct X
    {
        void find_me(X, int) {}
        void search();
    };
    void find_me(X, double) {}

    void X::search() {
        find_me(*this, 2.5); // only finds X::find_me(int)
        // pure unqualified lookup (1st step) finds the member function
        // argument-dependent lookup is not performed
    }
}

에:

namespace my_namespace
{
    struct X
    {
        void operator<<(int) {}
        void search();
    };
    void operator<<(X, double) {}

    void X::search() {
        *this << 2.5; // find both because both steps are always performed
        // and overload resolution selects the free function
    }
}

std::cout << "Hello, world!"; //calls std:::operator <<

This is achieved with Argument-dependent name lookup (ADL, aka Koenig Lookup)

Although we have only one std qualifier but there are two things that comes up from std namespace

  • cout
  • <<

Without ADL, (Koenig Lookup)

std::cout std:: << "Hello World" ;//this won't compile

In order to compile it, we need to use it more uglier form

std::operator<<(std::cout, "Hello, world!");

So to avoid such ugly syntax we must appreciate Koenig Lookup :)


The compiler sees that the arguments to << are an std::ostream object and a string, and so is able to locate the proper operator<< definition based on this.

You can sort of think of the argument types of an operator (or really, any function) as part of its name.

참고URL : https://stackoverflow.com/questions/19122575/why-i-have-to-write-stdcout-and-not-also-std

반응형