허스크 2022. 3. 6. 12:33
반응형

서론

 C++ 에서 정렬이 필요한 container용으로 pair를 주로 사용하는 편인데 평소 이것들을 넣을 때 make_pair 를 통해서 넣어주고 있었습니다. 그런데 다른 분드르이 코드를 보면 { } 안에 원소들을 넣어서 코드가 더 짧아보이는 일이 있었습니다. 평소에는 'make_pair이 최적화가 더 잘 되지 않을까?' 하는 생각에 계속 이를 사용했는데 이번에는 정확히 어떤 차이가 있는지 알아보도록 하겠습니다.

 

 

make_pair vs std::pair

 일단 넣는데 make_pair과 std::pair를 사용하는 방법이 있습니다.

#include <vector>

std::vector<std::pair<int, int>> vec;

int main(){
    vec.push_back(std::make_pair(1, 2));
    vec.push_back(std::pair<int, int>(1, 2));
}

 std::make_pair의 경우 인자들의 타입을 자동으로 매칭해 주지만 std::pair를 사용하는 경우 넣을 때마다 인자의 타입을 명시해줘야 한다는 단점이 있습니다. 이는 make_pair가 템플릿으로 되어 있어서 그렇습니다.

// C++ 11
template< class T1, class T2 >
std::pair<T1,T2> make_pair( T1 t, T2 u );

// C++ 14
template< class T1, class T2 >
constexpr std::pair<V1,V2> make_pair( T1&& t, T2&& u );

 

make_pair vs { } (Curly Brackets)

#include <vector>

std::vector<std::pair<int, int>> vec;

int main(){
    vec.push_back({1, 2});
}

 일단 위 { }를 사용하면 make_pair보다 훨씬 가독성이 좋아집니다. 그런데 중요한점은 성능상 큰 차이가 없냐 였습니다. 그래서 여기저기 본 결과 어디선가 어셈블리 코드를 구할 수 있었습니다.

  // make_pair
  mov eax, DWORD PTR x[rip]
  lea rsi, [rsp+24]
  mov DWORD PTR [rsp+24], eax
  mov eax, DWORD PTR y[rip]
  mov DWORD PTR [rsp+28], eax
  
  
  // { }
   mov eax, DWORD PTR x[rip]
  lea rsi, [rsp+24]
  mov edi, OFFSET FLAT:vec
  mov DWORD PTR [rsp+24], eax
  mov eax, DWORD PTR y[rip]
  mov DWORD PTR [rsp+28], eax

 edi 레지스터(메모리 주소를 알아내는 용도로 EBX 레지스터의 일부)에 offset을 더하는 코드가 더 있을 뿐 어셈블리 단에서 큰 차이가 없었습니다.

 

 

비교 연산 == 에서

 pair<T1, T2> 자료구조에 대한 비교가 필요한 때가 있습니다. 이때 C++17의 컴파일러와 이전의 컴파일러에 따라 코드가 달라지게 됩니다.

#include <vector>

std::pair<int, int> p;

int main(){
    p = {1, 2};

    if(p ==std::pair{1, 2}){
        // C++ 17
    }
    if(p == std::make_pair(1, 2)){
        // C++ 14
    }
}

  제가 가진 GCC 버전은 6.3.0 인데 17 버전을 지원해주지 않는지 위 std::pair{1, 2} 와의 비교가 불가능했습니다. 컴파일러 버전을 잘 체크해야 될 것 같네요.

 

참고 출처

- make_pair vs { } assembly

 

Difference between make_pair and curly brackets { } for assigning a pair in C++?

I didn't find anyone answering this, is there any difference between the following : v.push_back({x, y}); and : v.push_back(make_pair(x, y)); Assuming that v was declared this way : vector&l...

stackoverflow.com

- make_pair 템플릿 코드

 

std::make_pair - cppreference.com

template< class T1, class T2 > std::pair make_pair( T1 t, T2 u ); (until C++11) template< class T1, class T2 > std::pair make_pair( T1&& t, T2&& u ); (since C++11) (until C++14) template< class T1, class T2 > constexpr std::pair make_pair( T1&& t, T2&& u )

en.cppreference.com

- pair == operator

 

Pair and curly brace check

#include <bits/stdc++.h> using namespace std; int main() { pair<int,int>p = {1,3}; if (p=={1,3}) cout << "yeyey\n"; } I want to check whether this pai...

stackoverflow.com

 

반응형