我正在读这里: http://www.cplusplus.com/reference/deque/deque/push_back/
的
void push_back (const value_type& val);
val是
要复制(或移动)到新元素的值。
e.g。如果val是一个类的实例,在这种情况下它是否被复制并在其中被移动?这两种情况有什么区别?
您还可以解释以下每个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;
}
谢谢!
答案 0 :(得分:1)
如果val是一个类的实例,在这种情况下它会被复制并且 它被移动了吗?这两种情况有什么区别?
如果某个值是某个类的实例,那么就比如说
class MyValue {};
MyValue originalValue;
MyValue copyAssignedValue = originalValue;
它总是被复制。发生这种情况是因为调用了复制赋值运算符。在类似的事情中,
MyValue copyConstructedValue(originalValue);
调用复制构造函数(如名称所示,复制内容)。
要理解为什么以及何时使用复制或移动构造函数,有必要了解这两个操作之间的区别:
复制对象就像普通的复制和粘贴一样:您现在拥有可以独立处理的同一对象的两个副本。移动对象就像剪切和粘贴:最后只有一个工作对象,旧的被删除。然而,它比复制要快得多,因为你不需要分配新的内存。
要移动对象,您可以执行一些操作。例如,您可以创建一个编译器知道您只需要在移动构造函数中使用的对象。
MyValue moveConstructedValue(MyValue());
为了清楚起见,这就是移动构造函数的样子:
MyValue::MyValue(MyValue&& other);
注意双&&
,表示右值引用(单&
现在称为左值引用)。
或者你可以表明你想要显式使用移动构造函数(注意,originValue对象将被重置为默认值):
MyValue valueToBeMovedTo(std::move(originalValue));
回答你的第二个问题,你的哪个函数使用了一个移动操作:实际上,它们都没有将val“移动”到m_vals中,因为编译器不知道你以后是否想要使用它。您可以使用新的右值参考来移动:
void add_valMoving(const Value &&val)
{
m_vals.push_back( val );
}
要100%更正,add_val3使用移动构造函数,但不直接在val对象上:它首先调用Value的复制构造函数并将val复制到新对象中,然后使用移动构造函数将新对象移动到deque。
修改强>
要在移动对象时更清楚“默认值”,移动构造函数可以是:
class MyValue
{
public:
MyValue(MyValue&& other)
{
this->member = other.member;
other.member = 0;
}
private:
int member;
}
但是,您永远不会知道移动后原始对象的值。
答案 1 :(得分:1)
该引用让您感到困惑,因为默认情况下它只显示 复制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
}
答案 2 :(得分:0)
要复制(或移动)到新元素的值。
这取决于push_back
中使用的重载(请参阅this,在我看来,更好的参考页)。
add_val1
需要参考和push_back
副本
add_val2
取值(因此函数会复制它),而不是push_back
再次复制。{
add_val3
需要引用,您可以调用副本,但由于Value(val)
是r值,因此临时值会移动push_back
。