简体   繁体   English

为什么第二次初始化工作而第一个由于“元素类型不匹配”而失败?

[英]Why the second initialization work while the first one fail because of the "element type does not match"?

In c++ primer-initializing a Container as a copy of another container.在 C++ 入门中,将一个容器初始化为另一个容器的副本。

The element types in the new and original containers can differ as long as it is possible to convert the elements we are copying to the element type of the container we are initializing.只要可以将我们正在复制的元素转换为我们正在初始化的容器的元素类型,新容器和原始容器中的元素类型就可以不同。

For example:例如:

vector<const char*> articles = {"a", "an", "the"};
vector<string> words(articles) ; //error:element types must match
forward_list<string> words(articles.begin(), articles.end()); // ok, convert const char* to string

My question is why the second initialization work while the first one fail because of the element type does not match ?我的问题是为什么第二个初始化工作而第一个因为元素类型不匹配而失败?

The first line calls the constructor with an initializer_list of the same type as the element type ( const char*).第一行使用与元素类型 (const char*) 相同类型的 initializer_list 调用构造函数。 something like this:像这样:

vector<T>(initializer_list<T> t ) {....} 

--> OK! --> 好的!

The second is a copy-constructor call which is only defined for the same element type.第二个是复制构造函数调用,它只为相同的元素类型定义。

vector<T>(const& vector<T> t) {...}

What you did is something like this:你所做的是这样的:

vector<string>(const& vector<const char*> t){..}

--> Which does not exist! --> 哪个不存在!

First line performs copy-list-initialization (cfr. initializer_list constructor ).第一行执行 复制列表初始化(参见initializer_list构造函数)。

Second line has no matching constructor since the types don't match (it can't call a copy constructor).第二行没有匹配的构造函数,因为类型不匹配(它不能调用复制构造函数)。

Third line instead uses the iterator range constructor which emplace-constructs elements and has a viable const char* to string conversion to use.第三行改为使用迭代器范围构造函数,该构造函数用于构造元素并具有可行的const char*string转换以供使用。

My question is why the second initialization works while the first one fails我的问题是为什么第二次初始化工作而第一个失败

You're constructing a something .你正在构建一个东西 This isn't done by magic, it just has to call one of the something 's constructors.这不是靠魔法完成的,它只需要调用something的构造函数之一。 Any expression which can't match one of the constructors, can't compile.任何无法匹配其中一个构造函数的表达式都无法编译。


So, let's first consider所以,让我们首先考虑

vector<const char*> articles = {"a", "an", "the"};
vector<string> words(articles);

Now, we need some std::vector constructor that makes sense with this expression.现在,我们需要一些对这个表达式有意义的std::vector构造函数。 They're listed here , and the only ones that come close to matching are numbers 5 and 6 (at the time of writing - they're the copy and move constructors).它们在此处列出,唯一接近匹配的是数字 5 和 6(在撰写本文时 - 它们是复制和移动构造函数)。

The move constructor is out because we're not using std::move or otherwise working directly on an rvalue reference, so let's take a look at the copy constructor:因为我们没有使用std::move或以其他方式直接处理右值引用,所以移动构造函数已失效,所以让我们看看复制构造函数:

vector<string>::vector<string>(const vector<string> &other);

Note that this isn't templated to take any argument type, or to take a vector of any type: it only matches a const reference to a vector of exactly the same type.请注意,这不是模板化以采用任何参数类型,或采用任何类型的向量:它只匹配对完全相同类型的向量的 const 引用。 Even though const char * is implicitly convertible to std::string , the type vector<string> is still not the same as vector<const char *> .即使const char *可以隐式转换为std::string ,类型vector<string>仍然与vector<const char *> So, no constructor matches the argument type given.因此,没有构造函数与给定的参数类型匹配。


Then, consider然后,考虑

forward_list<string> words(articles.begin(), articles.end());

The std::forward_list constructors are listed here . 此处列出std::forward_list构造函数。 Note number 4:注意编号 4:

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

Firstly, this is templated on the iterator type, so passing vector<string>::iterator or vector<const char *>::iterator or whatever is no problem.首先,这是在迭代器类型上模板化的,因此传递vector<string>::iteratorvector<const char *>::iterator或任何问题都没有问题。 Secondly, the conversion to std::string from const char * is sufficient for this overload to actually compile once it is selected.其次,从const char *std::string的转换足以让这个重载在被选中后实际编译。


Now, a couple of notes:现在,有几个注意事项:

  1. You mentioned the explicit keyword: this just prevents a single-argument constructor being used as an implicit conversion.您提到了explicit关键字:这只是防止将单参数构造函数用作隐式转换。 It doesn't affect higher types though: even if string::string(const char *) is allowed as an implicit conversion, that doesn't make vector<const char *> convertible to vector<string> .不过,它不会影响更高的类型:即使允许string::string(const char *)作为隐式转换,也不会使vector<const char *>转换为vector<string> That still has to go through one of vector 's constructors.这仍然必须通过vector的构造函数之一。

  2. We're mostly talking here about how an overload (in this case an overloaded constructor) is selected.我们在这里主要讨论如何选择重载(在本例中为重载构造函数)。 It's entirely possible the compiler can select an overload, and then still fail to compile.完全有可能编译器可以选择重载,然后仍然无法编译。 For example, using that second iterator range constructor, where the iterators point to some incompatible (not even explicitly convertible) type.例如,使用第二个迭代器范围构造函数,其中迭代器指向一些不兼容(甚至不能显式转换)的类型。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么这里的第一个语句不违反受保护的访问,而第二个语句却不违反受保护的访问? - Why does the first statement here not violate protected access while the second one does? 为什么“新”在类初始化中失败 - Why does 'new' fail in class initialization 为什么第二个代码有效而第一个无效呢? - Why is it that the second code works while the first one doesnt? 为什么我的VC 2005 x64调试会话在第一次试用时始终失败(但在第二次试用中没有失败)? - Why does my VC 2005 x64 Debug session allways fail on first trial (but not on second trial)? 为什么第一个程序不起作用但第二个程序起作用?在第二个为什么输出是它给出的? - Why the first programme does not work but second works ? and in second why the output is as it gives? 为什么第二个 wxSizer 无法使按钮居中? - Why does the second wxSizer fail to center the button? 使用初始化列表的 POD 类型初始化不起作用 - POD type initialization using initialization list does not work 为什么decltype返回类型对递归模板失败,而返回类型推导工作正常? - Why does decltype return type fail for recursive template, while return type deduction works just fine? 为什么复制构造函数可以用于初始化,但不能用于赋值? - Why does copy constructor work for initialization, but not for assignment? 为什么在程序中有一个while循环之前,第二个while循环为什么不起作用? - Why does the second while loop in my program not work when there is a while loop before it?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM