为什么std :: pair <int,int =“”>可以从const std :: pair <int,float =“”>&amp;?</int,> </int,>中构造出来

时间:2013-12-09 21:47:34

标签: c++

使用here中的第4个定义,std::pair<int, int>似乎可隐式构建const std::pair<int, float>&

#include <iostream>
#include <vector>
#include <utility>

int main() {
    std::vector<std::pair<int, float>> v = { {1, 1.5f} };

    // The interesting line:
    const std::pair<int, int>& x = v[0];

    const auto& y = v[0];

    std::cout << "before:\n";
    std::cout << "\tv[0]: " << std::get<1>(v[0]) << "\n";
    std::cout << "\tx:    " << std::get<1>(x) << "\n";
    std::cout << "\ty:    " << std::get<1>(y) << "\n";

    std::get<1>(v[0]) = 3.5f;

    std::cout << "\nafter:\n";
    std::cout << "\tv[0]: " << std::get<1>(v[0]) << "\n";
    std::cout << "\tx:    " << std::get<1>(x) << "\n";
    std::cout << "\ty:    " << std::get<1>(y) << "\n";
}

输出

before:
    v[0]: 1.5
    x:    1
    y:    1.5

after:
    v[0]: 3.5
    x:    1
    y:    3.5

ideone link

x“感觉”不像引用而不是y似乎很尴尬(因为它(合法地)是从用户的角度引用可能是“错误”的东西。)

该构造函数未标记为explicit的原因是什么? (我假设有一个重要的用例。)

2 个答案:

答案 0 :(得分:3)

x不是v[0]的引用,它是对std::pair<int, int>类型的对象的引用,它与x的生命周期相匹配。初始化const T&时,如果无法直接引用,将从右侧构建新对象。

在这种情况下,你所写的内容与写作相同:

const std::pair<int, int> x = v[0]; // note: no reference

你应该对此有所警告,因为浮动转换为int。

答案 1 :(得分:3)

// The interesting line:
const std::pair<int, int>& x = v[0];

该代码相当于:

const std::pair<int,int>& x = std::pair<int,int>(v[0]);

让您感到惊讶的问题是,由于存在从std::pair<int,float>std::pair<int,int>的转换,编译器被允许(并且需要)创建临时文件并将const引用绑定到该文件。如果删除const(并且您没有使用VS),则代码应该失败。