如果我有这样的类型:
class Foo {
public:
Foo();
Foo(const Foo&);
Foo& operator=(const Foo&) = delete;
...
private:
...
};
我有两个这种类型的载体:
std::vector<Foo> x;
std::vector<Foo> y;
我想将x
的内容复制到y
,是否有跨平台的方式?
VC ++将使用y.assign(x.begin(), x.end())
执行此操作,Foo
使用y = x
的复制构造函数而不是已删除的复制赋值运算符。但是,无论您是尝试y.assign(x.begin(), x.end())
还是<?php
$this->registerJs('
jQuery(document).on("change" ,"#'. Html::getInputId($model ,'Test2') .'" ,function(){
$("#'. Html::getInputId($model ,'Test3') .'").val();
var first = $("#'. Html::getInputId($model ,'Test1') .'").val();
var second = $("#'. Html::getInputId($model ,'Test2') .'").val();
var third = first +" " + second;
$("#'. Html::getInputId($model ,'Test3') .'").val(third);
});
');
?>
,GCC都会抱怨丢失的副本分配运算符。
是否有某种方法适用于两者?
答案 0 :(得分:4)
该标准要求y.assign(it1, it2)
生效,元素类型T
为 CopyAssignable 。也就是说,复制可构造和可分配。您的类型不可分配,因此您无法依赖assign
。 y = x
也是如此。该标准的第23.2.3节描述了各种序列容器操作的要求。
如果您有现有的向量y
,则可以构建一个新的向量z
,然后将其与y
交换:
{
std::vector<Foo> z(x.begin(), x.end());
z.swap(y);
}
这使用范围构造函数,只需要T
为EmplaceConstructible
,不需要赋值操作符!然后,您可以交换底层内存而无需进一步复制。
请注意,这可能会导致更大的内存使用量,因为y
的任何现有内容都会一直存在,直到新交换的z
超出范围。您可以先尝试
y.clear();
y.shrink_to_fit();
虽然shrink_to_fit()
只是一个请求,但您的库实现可能无法遵守。
答案 1 :(得分:2)
在C ++ 11之前,您的代码是不可能的:向量元素类型必须是CopyAssignable
,这意味着可复制构造和可分配。请注意,如果类型不符合这些要求,则代码格式错误,无需诊断;这使编制者能够接受或拒绝它。
从C ++ 11开始,个别操作都有自己的要求。 vector
的相关要求是(来源:C ++ 14表100):
emplace_back
:MoveInsertible
和MoveAssignable
insert
:CopyInsertable
和CopyAssignable
EmplaceConstructible
这些特征的含义是(粗略地):
CopyInsertable
:有copy-constructor MoveInsertable
:具有copy-constructor或move-constructor(或两者)CopyAssignable
:具有复制构造函数和复制赋值运算符MoveAssignable
:MoveInsertable
,并具有复制分配或移动分配运算符(或两者)EmplaceConstructible
:有构造函数这里的基本原理是任何插入都可能导致内存重新分配,要求您的对象可以被复制或移动。但是,标准不要求编译器测试构造函数或赋值运算符是否都可用,如果不是另一个,则使用一个。相反,它指定两者都必须可用。
您没有指定您的班级是否可以移动。假设它不是,则意味着您不能使用任何emplace或insert方法,也不能使用任何其他可能导致重新分配的函数。
如果您当时正在创建y
,那么您当然可以使用初始化:
vector<int> y = x;
如果y
已经存在,正如您的问题似乎表明的那样,那么您几乎不运气:您无法使用任何插入功能,因此您只能修改现有元素。由于没有赋值运算符,因此无法通过赋值执行此操作。
但您可以按照Andrew的回答中的建议使用y.swap()
。
考虑将move-constructor和move-assignment添加到您的类中,或重新设计代码,以便您不需要分配给y
。 (例如,使用指针)。
如果x.size() == y.size()
,您可以使用展示位置作为最后的黑客攻击:
for (size_t i = 0; i != y.size(); ++i)
{
y[i].~Foo();
new(&y[i]) Foo(x[i]); // copy-construct
}