vector - 当元素有 const 成员时交换两个元素
vector - swap two elements when elements have const members
我有以下代码
class a {
public:
const int aa;
a(int aa) : aa(aa){}
};
int main() {
std::vector<a> v;
v.emplace_back(1);
v.emplace_back(2);
v.emplace_back(3);
v.emplace_back(4);
std::iter_swap(v.begin() + 1, v.rbegin());
system("pause");
return 0;
}
当我尝试交换向量的两个元素时出现错误。
Error C2280 'a &a::operator =(const a &)': attempting to reference a deleted function
我明白这是因为 a
有一个常量成员,但我不知道如何让它工作。
问题是 swap
更改了现有元素的值。由于元素是常量,因此无法更改它们,因此会出现编译器错误。
如果您坚持使用 const 元素,您的矢量应该 vector<a*>
或更好 vector<unique_ptr<a>>
。这将允许您在不改变 a
的实际元素的情况下交换元素
有可能。由于 std::iter_swap
for std::vector
迭代器实现看起来像这样:
using std::swap;
swap(*iter1, *iter2);
您可以定义自己的swap
函数:
class A {
const int aa;
public:
A(int aa) : aa(aa){}
void swap(A &other)
{
std::swap(const_cast<int &>(aa), const_cast<int &>(other.aa));
}
};
void inline swap(A &a1, A &a2)
{
a1.swap(a2);
}
它 works!
有关此工作原理的更多信息,请参阅著名的 Scott Meyers 书籍 "Effective C++",规则 25。如果您找不到,我可以尝试解释它(迈耶斯先生做得更好, 我认为).
当对象很大时,@doron 关于指针向量的提示是一个非常好的选择。
编辑
@Yakk 建议将 const 变量转换为非常量变量会导致未定义的行为。 最好不要用这种方式
基于 this 线程以下作品:
#include <vector>
#include <iostream>
class Foo {
public:
const int value;
Foo(const int &&from) : value(std::move(from)){}
Foo(const Foo &&other) : value(std::move(other.value)){}
Foo & operator=(Foo && source) {
this -> ~ Foo ();
new (this) Foo(std::move(source));
return *this;
}
};
int main() {
std::vector<Foo> v;
v.emplace_back(1);
v.emplace_back(2);
v.emplace_back(3);
v.emplace_back(4);
std::cout << (v.begin() + 1)->value << "," <<v.rbegin()->value << std::endl;
std::iter_swap(v.begin() + 1, v.rbegin());
std::cout << (v.begin() + 1)->value << "," <<v.rbegin()->value << std::endl;
return 0;
}
它也可以在没有 r 值和 std::move
的情况下工作
const a& operator=(const a &other)
{
this->~a();
new (this) a(other.aa);
return *this;
}
我有以下代码
class a {
public:
const int aa;
a(int aa) : aa(aa){}
};
int main() {
std::vector<a> v;
v.emplace_back(1);
v.emplace_back(2);
v.emplace_back(3);
v.emplace_back(4);
std::iter_swap(v.begin() + 1, v.rbegin());
system("pause");
return 0;
}
当我尝试交换向量的两个元素时出现错误。
Error C2280 'a &a::operator =(const a &)': attempting to reference a deleted function
我明白这是因为 a
有一个常量成员,但我不知道如何让它工作。
问题是 swap
更改了现有元素的值。由于元素是常量,因此无法更改它们,因此会出现编译器错误。
如果您坚持使用 const 元素,您的矢量应该 vector<a*>
或更好 vector<unique_ptr<a>>
。这将允许您在不改变 a
有可能。由于 std::iter_swap
for std::vector
迭代器实现看起来像这样:
using std::swap;
swap(*iter1, *iter2);
您可以定义自己的swap
函数:
class A {
const int aa;
public:
A(int aa) : aa(aa){}
void swap(A &other)
{
std::swap(const_cast<int &>(aa), const_cast<int &>(other.aa));
}
};
void inline swap(A &a1, A &a2)
{
a1.swap(a2);
}
它 works!
有关此工作原理的更多信息,请参阅著名的 Scott Meyers 书籍 "Effective C++",规则 25。如果您找不到,我可以尝试解释它(迈耶斯先生做得更好, 我认为).
当对象很大时,@doron 关于指针向量的提示是一个非常好的选择。
编辑
@Yakk 建议将 const 变量转换为非常量变量会导致未定义的行为。 最好不要用这种方式
基于 this 线程以下作品:
#include <vector>
#include <iostream>
class Foo {
public:
const int value;
Foo(const int &&from) : value(std::move(from)){}
Foo(const Foo &&other) : value(std::move(other.value)){}
Foo & operator=(Foo && source) {
this -> ~ Foo ();
new (this) Foo(std::move(source));
return *this;
}
};
int main() {
std::vector<Foo> v;
v.emplace_back(1);
v.emplace_back(2);
v.emplace_back(3);
v.emplace_back(4);
std::cout << (v.begin() + 1)->value << "," <<v.rbegin()->value << std::endl;
std::iter_swap(v.begin() + 1, v.rbegin());
std::cout << (v.begin() + 1)->value << "," <<v.rbegin()->value << std::endl;
return 0;
}
它也可以在没有 r 值和 std::move
的情况下工作const a& operator=(const a &other)
{
this->~a();
new (this) a(other.aa);
return *this;
}