std :: make_pair与std :: pair的构造函数的目的是什么?

166 c++ stl std-pair

目的是std::make_pair什么?

为什么不std::pair<int, char>(0, 'a')呢?

这两种方法有什么区别吗?

Tor*_*amo 153

不同之处在于,std::pair您需要指定两个元素的类型,而std::make_pair将创建一个具有传递给它的元素类型的对,而无需您告诉它.无论如何,这就是我可以从各种文档中收集的内容.

请参阅http://www.cplusplus.com/reference/std/utility/make_pair/上的此示例

pair <int,int> one;
pair <int,int> two;

one = make_pair (10,20);
two = make_pair (10.5,'A'); // ok: implicit conversion from pair<double,char>
Run Code Online (Sandbox Code Playgroud)

除了它的隐式转换奖励,如果你没有使用make_pair,你必须这样做

one = pair<int,int>(10,20)
Run Code Online (Sandbox Code Playgroud)

每次你分配给一个,这会随着时间的推移而烦人...

  • 我认为你现在可以做`one = {10,20}`但是我没有C++ 11编译器来检查它. (14认同)
  • 另请注意,`make_pair`适用于未命名的类型,包括结构,联合,lambdas和其他装饰. (5认同)
  • 实际上,类型应该在编译时推导出来,而不需要指定。 (2认同)

Pla*_*mer 33

正如@MSalters上面回复的那样,您现在可以使用花括号在C++ 11中执行此操作(只需使用C++ 11编译器验证):

pair<int, int> p = {1, 2};
Run Code Online (Sandbox Code Playgroud)


dev*_*vil 25

使用make_pair和显式调用pair具有指定类型参数的构造函数之间没有区别.std::make_pair当类型冗长时更方便,因为模板方法具有基于其给定参数的类型推导.例如,

std::vector< std::pair< std::vector<int>, std::vector<int> > > vecOfPair;
std::vector<int> emptyV;

// shorter
vecOfPair.push_back(std::make_pair(emptyV, emptyV));

 // longer
vecOfPair.push_back(std::pair< std::vector<int>, std::vector<int> >(emptyV, emptyV));
Run Code Online (Sandbox Code Playgroud)


mkm*_*mkm 21

值得注意的是,这是C++模板编程中常见的习惯用法.它被称为Object Generator习语,你可以在这里找到更多信息和一个很好的例子.

编辑正如有人在评论中建议的那样(自删除后),以下是链接中略有修改的摘录,以防它中断.

对象生成器允许在不明确指定其类型的情况下创建对象.它基于函数模板的有用属性,类模板没有:函数模板的类型参数是从其实际参数中自动推导出来的.std::make_pair是一个简单的示例,它std::pair根据std::make_pair函数的实际参数返回模板的实例.

template <class T, class U>
std::pair <T, U> 
make_pair(T t, U u)
{
  return std::pair <T, U> (t,u);
}
Run Code Online (Sandbox Code Playgroud)

  • @duck实际上是从C ++ 11开始的&amp;&amp;`。 (2认同)

Cir*_*四事件 20

在C++ 17之前,无法从构造函数中推断出类模板参数

在C++ 17之前你不能写出类似的东西:

std::pair p(1, 'a');
Run Code Online (Sandbox Code Playgroud)

因为这会从构造函数参数中推断出模板类型.

C++ 17使该语法成为可能,因此是make_pair多余的.

在C++ 17之前,std::make_pair允许我们编写更简洁的代码:

MyLongClassName1 o1();
MyLongClassName2 o2();
auto p = std::make_pair(o1, o2);
Run Code Online (Sandbox Code Playgroud)

而不是更详细:

std::pair<MyLongClassName1,MyLongClassName2> p{o1, o2};
Run Code Online (Sandbox Code Playgroud)

重复的类型,可以很长.

类型推断适用于前C++ 17案例,因为make_pair它不是构造函数.

make_pair 基本上相当于:

template<class T1, class T2>
std::pair<T1, T2> my_make_pair(T1 t1, T2 t2) {
    return std::pair<T1, T2>(t1, t2);
}
Run Code Online (Sandbox Code Playgroud)

同样的概念也适用于inserterVS insert_iterator.

也可以看看:

  • _“C++17 使该语法成为可能,因此 make_pair 是多余的。”_ - 为什么 `std::make_pair` 在 C++17 中没有被弃用? (3认同)
  • @andreee我不确定,可能的原因是它不会造成任何麻烦,所以不需要破坏旧代码?但我不熟悉 C++ 委员会的基本原理,如果你发现了什么,请告诉我。 (3认同)
  • 我遇到的一件有用的事情是,能够使用 std::make_pair&lt;T1, T2&gt;(o1, o2) 指定类型可以防止用户错误地传递不能隐式传递的类型 o1 或 o2投射到 T1 或 T2。例如将负数传递给无符号整数。-Wsign-conversion -Werror 不会在 c++11 中使用 std::pair 构造函数捕获此错误,但如果使用 std::make_pair 它将捕获该错误。 (3认同)

Emp*_*oli 5

make_pair 在直接构造函数上创建一个额外的副本。我总是 typedef 我的对以提供简单的语法。
这显示了差异(Rampal Chaudhary 的示例):

class Sample
{
    static int _noOfObjects;

    int _objectNo;
public:
    Sample() :
        _objectNo( _noOfObjects++ )
    {
        std::cout<<"Inside default constructor of object "<<_objectNo<<std::endl;
    }

    Sample( const Sample& sample) :
    _objectNo( _noOfObjects++ )
    {
        std::cout<<"Inside copy constructor of object "<<_objectNo<<std::endl;
    }

    ~Sample()
    {
        std::cout<<"Destroying object "<<_objectNo<<std::endl;
    }
};
int Sample::_noOfObjects = 0;


int main(int argc, char* argv[])
{
    Sample sample;
    std::map<int,Sample> map;

    map.insert( std::make_pair( 1, sample) );
    //map.insert( std::pair<int,Sample>( 1, sample) );
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • 如果编译器的优化设置足够高,我很确定在所有情况下都会忽略额外的副本。 (4认同)