为什么带有两个元素的初始化语法将一个元素而不是两个元素放到字符串向量中?

问题描述 投票:1回答:1

为什么我在b中得到一个元素而不是两个?在a中,我得到了预期的一个,在c中,我得到了预期的三个元素。具有两个值的一个在某种程度上是一种特殊情况。

#include <string>
#include <vector>
#include <iostream>

void print(const std::string& name, const std::vector<std::string>& v)
{
    std::cout << name << ' ' << v.size() << '\n';
    for (const auto& str : v) {
        std::cout << str << '\n';
    }
    std::cout << "\n";
}

int main()
{
    std::vector<std::string> a = {{"str1"}};
    std::vector<std::string> b = {{"str1", "str2"}};
    std::vector<std::string> c = {{"str1", "str2", "str3"}};
    print("a", a);
    print("b", b);
    print("c", c);
    return 0;
}

此打印:

a 1
str1

b 1
str1

c 3
str1
str2
str3

我想这与向量ctor的重载有关。

template< class InputIt >
vector( InputIt first, InputIt last,
    const Allocator& alloc = Allocator() );

我使用clang 9.0.0和-std=c++17 -O2 -Wall作为标志。

b,编译器做了什么?为什么在一种情况下确定它是迭代器而在其他情况下确定它是初始化器列表?我的示例代码定义是否正确,或者是否具有UB?

c++ string vector list-initialization
1个回答
1
投票

我的示例代码定义是否正确,或者它具有UB?

它确实有UB。采用first-last迭代器对的构造函数假定两个迭代器都引用相同的序列。 {{"str1"}, {"str2"}}不满足此要求,因此为UB。

b,编译器做了什么?为什么在一种情况下决定将其确定为迭代器,而在其他情况下为何将其确定为初始化器列表?

回想一下,字符串文字“ str1”的类型为char const[5]。但是,对std::initializer_list的构造函数重载的调用适用于std::string实例。这需要隐式转换-并且由于两个迭代器的构造函数模板不需要这种转换,因此认为是更好的匹配。


您可以通过以下方式解决此问题

std::vector<std::string> b2 = {"str1", "str2"};

std::vector<std::string> b3 = {{std::string("str1"), "str2"}};
© www.soinside.com 2019 - 2024. All rights reserved.