c++ 当你在双端队列中 push_back 或 push_front 时真正发生了什么
c++ what really happens when you push_back or push_front in a deque
我正在阅读这里:
http://www.cplusplus.com/reference/deque/deque/push_back/
为
void push_back (const value_type& val);
val 是一个
Value to be copied (or moved) to the new element.
例如如果 val 是 class 的实例,在哪种情况下它会被复制并移动?这两种情况有什么区别?
您能否也解释一下以下 add_val1、add_val2 和 add_val3 中的每一个有何不同?
#include <deque>
class Value
{
int member1;
int member2;
};
class ValuesContainer
{
private:
std::deque<Value> m_vals;
public:
void add_val1(const Value &val)
{
m_vals.push_back( val );
}
void add_val2(const Value val)
{
m_vals.push_back( val );
}
void add_val3(const Value &val)
{
m_vals.push_back( Value(val) );
}
};
int main()
{
return 0;
}
谢谢!
Value to be copied (or moved) to the new element.
这取决于 push_back
中使用的重载(参见 this,在我看来,更好的参考页面)。
add_val1
参考,push_back
复制。
add_val2
获取值(因此函数将复制它)然后由 push_back
.
再次复制
add_val3
获取引用,您调用一个副本,但由于 Value(val)
是 r 值,因此临时文件将移动 push_back
。
if val is an instance of a class, in which case does it get copied and
in which it gets moved? What is the difference between the two cases?
如果一个值是 class 的一个实例,比方说
class MyValue {};
MyValue originalValue;
MyValue copyAssignedValue = originalValue;
它总是被复制。发生这种情况是因为调用了复制赋值运算符。在类似的事情中,
MyValue copyConstructedValue(originalValue);
调用复制构造函数(顾名思义,它复制内容)。
要了解为什么以及何时使用复制或移动构造函数,有必要了解这两种操作之间的区别:
复制对象就像普通的复制和粘贴:您现在拥有同一对象的两个副本,您可以独立处理它们。移动一个对象就像剪切和粘贴:最后只有一个工作对象,旧的被删除。但是,它比复制快得多,因为您不需要分配新内存。
要移动对象,您可以做几件事。例如,您可以创建一个编译器知道您只需要在移动构造函数中使用的对象。
MyValue moveConstructedValue(MyValue());
为了清楚起见,这就是移动构造函数的样子:
MyValue::MyValue(MyValue&& other);
注意双 &&
,表示右值引用(单个 &
现在称为左值引用)。
或者您可以表明要显式使用移动构造函数(注意,originValue 对象将被重置为默认值):
MyValue valueToBeMovedTo(std::move(originalValue));
回答你的第二个问题,你的哪个函数使用了移动操作:实际上,none 其中 "move" 将 val 转换为 m_vals,因为编译器不知道如果你想以后使用它。您可以通过使用新的右值引用来移动:
void add_valMoving(const Value &&val)
{
m_vals.push_back( val );
}
为了100%正确,add_val3使用移动构造函数,但不是直接在val对象上:它首先调用Value的复制构造函数并将val复制到一个新对象中,然后使用移动构造函数将新对象移动到双端队列中。
编辑:
为了在移动对象时更清楚"default values",移动构造函数可以是:
class MyValue
{
public:
MyValue(MyValue&& other)
{
this->member = other.member;
other.member = 0;
}
private:
int member;
}
但是,您永远不知道移动后原始对象将设置为什么值。
那个引用让你感到困惑,因为它默认显示 仅 复制 push_back
,并且还在谈论移动。
自C++11起,有两个 push_back
s
void push_back( const T& value );
总是复制
void push_back( T&& value );
总是移动
如果你推回的值有一个名称,或者明确是一个T&
,那么它将使用第一个,否则使用第二个
void add_val1(const Value &val)
{
m_vals.push_back( val ); // copy
}
void add_val2(const Value val)
{
m_vals.push_back( val ); // copy
}
void add_val3(const Value &val)
{
m_vals.push_back( Value(val) ); // move the temporary that is a copy of val
}
extern Value make_value_somehow()
void add_val4()
{
m_vals.push_back( make_value_somehow() ); // move
}
extern Value& find_value_somehow()
void add_val5()
{
m_vals.push_back( find_value_somehow() ); // copy
}
void add_val6(Value val)
{
m_vals.push_back( val ); // copy
}
void add_val7(Value val)
{
m_vals.push_back( std::move(val) ); // move
}
void add_val8(const Value val)
{
// m_vals.push_back( std::move(val) ); // ill-formed, can't modify val
}
void add_val9(Value & val)
{
m_vals.push_back( std::move(val) ); // move, which will confuse people
}
我正在阅读这里: http://www.cplusplus.com/reference/deque/deque/push_back/
为
void push_back (const value_type& val);
val 是一个
Value to be copied (or moved) to the new element.
例如如果 val 是 class 的实例,在哪种情况下它会被复制并移动?这两种情况有什么区别?
您能否也解释一下以下 add_val1、add_val2 和 add_val3 中的每一个有何不同?
#include <deque>
class Value
{
int member1;
int member2;
};
class ValuesContainer
{
private:
std::deque<Value> m_vals;
public:
void add_val1(const Value &val)
{
m_vals.push_back( val );
}
void add_val2(const Value val)
{
m_vals.push_back( val );
}
void add_val3(const Value &val)
{
m_vals.push_back( Value(val) );
}
};
int main()
{
return 0;
}
谢谢!
Value to be copied (or moved) to the new element.
这取决于 push_back
中使用的重载(参见 this,在我看来,更好的参考页面)。
add_val1
参考,push_back
复制。
add_val2
获取值(因此函数将复制它)然后由 push_back
.
再次复制
add_val3
获取引用,您调用一个副本,但由于 Value(val)
是 r 值,因此临时文件将移动 push_back
。
if val is an instance of a class, in which case does it get copied and in which it gets moved? What is the difference between the two cases?
如果一个值是 class 的一个实例,比方说
class MyValue {};
MyValue originalValue;
MyValue copyAssignedValue = originalValue;
它总是被复制。发生这种情况是因为调用了复制赋值运算符。在类似的事情中,
MyValue copyConstructedValue(originalValue);
调用复制构造函数(顾名思义,它复制内容)。
要了解为什么以及何时使用复制或移动构造函数,有必要了解这两种操作之间的区别:
复制对象就像普通的复制和粘贴:您现在拥有同一对象的两个副本,您可以独立处理它们。移动一个对象就像剪切和粘贴:最后只有一个工作对象,旧的被删除。但是,它比复制快得多,因为您不需要分配新内存。
要移动对象,您可以做几件事。例如,您可以创建一个编译器知道您只需要在移动构造函数中使用的对象。
MyValue moveConstructedValue(MyValue());
为了清楚起见,这就是移动构造函数的样子:
MyValue::MyValue(MyValue&& other);
注意双 &&
,表示右值引用(单个 &
现在称为左值引用)。
或者您可以表明要显式使用移动构造函数(注意,originValue 对象将被重置为默认值):
MyValue valueToBeMovedTo(std::move(originalValue));
回答你的第二个问题,你的哪个函数使用了移动操作:实际上,none 其中 "move" 将 val 转换为 m_vals,因为编译器不知道如果你想以后使用它。您可以通过使用新的右值引用来移动:
void add_valMoving(const Value &&val)
{
m_vals.push_back( val );
}
为了100%正确,add_val3使用移动构造函数,但不是直接在val对象上:它首先调用Value的复制构造函数并将val复制到一个新对象中,然后使用移动构造函数将新对象移动到双端队列中。
编辑:
为了在移动对象时更清楚"default values",移动构造函数可以是:
class MyValue
{
public:
MyValue(MyValue&& other)
{
this->member = other.member;
other.member = 0;
}
private:
int member;
}
但是,您永远不知道移动后原始对象将设置为什么值。
那个引用让你感到困惑,因为它默认显示 仅 复制 push_back
,并且还在谈论移动。
自C++11起,有两个 push_back
s
void push_back( const T& value );
总是复制void push_back( T&& value );
总是移动
如果你推回的值有一个名称,或者明确是一个T&
,那么它将使用第一个,否则使用第二个
void add_val1(const Value &val)
{
m_vals.push_back( val ); // copy
}
void add_val2(const Value val)
{
m_vals.push_back( val ); // copy
}
void add_val3(const Value &val)
{
m_vals.push_back( Value(val) ); // move the temporary that is a copy of val
}
extern Value make_value_somehow()
void add_val4()
{
m_vals.push_back( make_value_somehow() ); // move
}
extern Value& find_value_somehow()
void add_val5()
{
m_vals.push_back( find_value_somehow() ); // copy
}
void add_val6(Value val)
{
m_vals.push_back( val ); // copy
}
void add_val7(Value val)
{
m_vals.push_back( std::move(val) ); // move
}
void add_val8(const Value val)
{
// m_vals.push_back( std::move(val) ); // ill-formed, can't modify val
}
void add_val9(Value & val)
{
m_vals.push_back( std::move(val) ); // move, which will confuse people
}