简体   繁体   English

移动构造函数和预增量与后增量

[英]Move constructor and pre-increment vs post-increment

In C++, if you have a for loop that "copies" objects of a user defined type using a move constructor, does it make any difference if you use ++i or i++ as the loop counter? 在C ++中,如果你有一个使用移动构造函数“复制”用户定义类型的对象的for循环,那么如果你使用++ii++作为循环计数器会有什么不同吗?

I know this question seems rather vague, but I was (I believe) asked this in a phone interview. 我知道这个问题看起来很模糊,但我(我相信)在电话采访中问过这个问题。 I wasn't sure if I understood the question correctly, and the interviewer took this as my not knowing the answer, and cut the interview short. 我不确定我是否正确地理解了这个问题,面试官把这个看作是我不知道答案,并简短地缩短了面试时间。

What could he have been getting at? 他能得到什么?

In C++, if you have a for loop that "copies" objects of a user defined type using a move constructor [...] 在C ++中,如果你有一个for循环使用移动构造函数“复制”用户定义类型的对象[...]

First of all, a move constructor is used for move-constructing, which usually means you are not "copying": you can realize moving as copying - in fact, a class which is copy-constructible is also move-constructible - but then why defining a move constructor explicitly? 首先,移动构造函数用于移动构造,这通常意味着你不是“复制”:你可以实现移动作为复制 - 事实上,一个可复制构造的类也是可移动构造的 - 但是为什么明确定义移动构造函数?

[...] does it make any difference if you use ++i or i++ as the loop counter? [...]如果你使用++ i或i ++作为循环计数器会有什么不同吗?

It depends on what i is. 这取决于i是什么。 If it is a scalar object, like an int , then there is no difference at all. 如果它是一个标量对象,就像一个int ,那么根本就没有区别。

If i is a class-type iterator, on the other hand, ++i should be more efficient (on a purely theoretical ground), because the implementation of operator ++ will not have to create a copy of the iterator to be returned before the iterator itself is incremented. 另一方面,如果i是类型迭代器,那么++i应该更高效(在纯粹的理论基础上),因为operator ++的实现不必创建迭代器的副本以便在之前返回迭代器本身会递增。

Here, for instance, is how stdlibc++ defines the increment operators for the iterator type of an std::list : 例如,stdlibc ++是如何定义std::list的迭代器类型的增量运算符的:

_Self&
operator++()
{
    _M_node = _M_node->_M_next;
    return *this;
}

_Self
operator++(int)
{
    _Self __tmp = *this;
    _M_node = _M_node->_M_next;
    return __tmp;
}

As you can see, the postfix version (the one accepting a dummy int ) has more work to do: it needs to create a copy of the original iterator to be refurned, then alter the iterator's internal pointer, then return the copy. 正如您所看到的,后缀版本(接受虚拟int )还有更多工作要做:它需要创建要重新生成的原始迭代器的副本,然后更改迭代器的内部指针,然后返回副本。

On the other hand, the prefix version just has to alter the internal pointer and return (a reference to) itself. 另一方面,前缀版本只需要改变内部指针并返回(引用)本身。

However, please keep in mind that when performance is concerned, all assumptions have to be backed up by measurement. 但是,请记住,在考虑性能时,所有假设都必须通过测量来支持。 In this case, I do not expect any sensible difference between these two functions. 在这种情况下,我不认为这两个功能之间有任何明显的区别。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM