vector - 当元素具有const成员

时间:2016-08-31 09:28:07

标签: c++ c++11 vector const swap

我有以下代码

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有一个常数成员,但我无法弄清楚如何让它发挥作用。

4 个答案:

答案 0 :(得分:11)

问题是swap会更改现有元素的值。由于元素是const,因此无法更改它们因此编译器错误。

如果你坚持使用const元素,你的向量应该是vector<a*>或事件更好vector<unique_ptr<a>>。这将允许您交换元素而不会改变a

的实际元素

答案 1 :(得分:2)

基于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;
}

答案 2 :(得分:0)

有可能。由于std::iter_swap 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书和#34; Effective C ++&#34;,规则25.如果找不到,我可以尝试解释它(我认为,迈尔斯先生做得更好)。

当对象很大时,@ doron关于指针向量的提示是一个非常好的选择。

修改

@Yakk建议将const变量强制转换为非const变量是导致未定义的行为。 最好不要这样使用。

答案 3 :(得分:0)

它也适用于没有r值和std :: move

const a& operator=(const a &other)
{
    this->~a();
    new (this) a(other.aa);
    return *this;
}