我有一个可复制构造的结构向量,但不可赋值:
std::vector<Struct>
这一切都很好。事实上,我甚至可以将值std::vector<TextFragment> v1, v2;
v2 = v1;
传递给函数的返回值。然而,这失败了:
private void insert_Click(object sender, EventArgs e)
{
SqlConnection Conectare = new SqlConnection();
Conectare.ConnectionString = @"Data Source=.\SQLEXPRESS;
AttachDbFilename=|DataDirectory|\Cuvinte.mdf;
Integrated Security=True;User
Instance=True ";
SqlDataAdapter da = new SqlDataAdapter();
da.InsertCommand = new SqlCommand("INSERT INTO Tabel_Cuvinte(id,cuv_ger,cuv_eng)"+" VALUES (@id, @cuv_ger,@cuv_eng)", Conectare);
da.InsertCommand.Parameters.Add("@id", SqlDbType.Int).Value = txtnr.Text;
da.InsertCommand.Parameters.Add("@cuv_ger", SqlDbType.VarChar).Value = txtger.Text;
da.InsertCommand.Parameters.Add("@cuv_eng", SqlDbType.VarChar).Value= txteng.Text;
Conectare.Open();
da.InsertCommand.ExecuteNonQuery();
Conectare.Close();
}
错误当然是:
错误:C2280:'Struct&amp; Struct :: operator =(const Struct&amp;)': 试图引用已删除的功能
我不明白它为什么试图调用它。这是否是某种优化以避免重新分配向量的内存块?..
答案 0 :(得分:4)
这是否是某种优化以避免重新分配向量的内存块?..
几乎。这是一种优化,可以避免重新分配vector
value_type
中可能存在的任何内存块。也就是说,这是一个全局假设,即赋值可以比复制构造后的破坏更有效。
例如,考虑vector<string>
分配,对于两个大小相等的vector
,以及string
中每个小点中的一堆大小相同的vector
:
v2 = v1;
所有这一操作都必须memcpy
每个string
。根本没有分配。减少分配/解除分配是目前存在的最重要的优化之一。
但是,Struct
并没有丢失所有内容。您要做的是指示vector
您不希望分配Struct
,而是破坏它们,然后从v1
复制它们。这样做的语法是:
v2.clear();
for (const auto& x : v1)
v2.push_back(x);
如下面的评论中所述,您还可以复制构建v1
,然后复制swap
。您需要创建v1
的临时本地副本,或者需要在&#34; lhs&#34;上使用v1
。成员互换:
std::vector<Struct>(v1).swap(v2);
我个人认为这很难读。在C ++ 11/14中,我更喜欢这种涉及移动分配的替代方案:
v2 = std::vector<Struct>(v1);
这些替代方案在眼睛上更容易。但使用clear()
和push_back
的第一种方法是平均效率最高的方案。这是因为第一个替代方案是唯一有可能在capacity()
中重用v2
的方案。其他两个总是在capacity()
的副本中重新创建新的v1
,并丢弃v2
现有的capacity()
。
答案 1 :(得分:3)
std::vector
是一个支持分配器的容器。如果我们查看规范(表99),我们a = t
其中a
是非常数左值,而t
是左值或常数右值,需要
T是CopyInsertable到X和 CopyAssignable 。发布:a == t
强调我的
其中T
是value_type
({1}}(容器)的X
。它还指出该操作是线性的。由于T
必须为CopyAssignable且Struct
不是CopyAssignable,因此无需工作。
这意味着赋值操作看起来像:
std::vector<T>& operator=(const std::vector<T>& rhs)
{
// allocate enough room for data if needed
for (std::size_t i = 0; i < rhs.size(); ++i)
data[i] = rhs.data[i];
return *this;
}
答案 2 :(得分:0)
您可以从libc ++中找到此功能的信息。请特别注意对std::copy
的调用。
template <class _Tp, class _Allocator>
template <class _ForwardIterator>
typename enable_if
<
__is_forward_iterator<_ForwardIterator>::value &&
is_constructible<
_Tp,
typename iterator_traits<_ForwardIterator>::reference>::value,
void
>::type
vector<_Tp, _Allocator>::assign(_ForwardIterator __first, _ForwardIterator __last)
{
size_type __new_size = static_cast<size_type>(_VSTD::distance(__first, __last));
if (__new_size <= capacity())
{
_ForwardIterator __mid = __last;
bool __growing = false;
if (__new_size > size())
{
__growing = true;
__mid = __first;
_VSTD::advance(__mid, size());
}
pointer __m = _VSTD::copy(__first, __mid, this->__begin_);
if (__growing)
__construct_at_end(__mid, __last, __new_size - size());
else
this->__destruct_at_end(__m);
}
else
{
deallocate();
allocate(__recommend(__new_size));
__construct_at_end(__first, __last, __new_size);
}
}
operator =
在修复分配器后,只需调用assign(r.begin(), r.end())
即可。