什么是禁用赋值运算符优化的GCC选项

时间:2014-07-15 07:25:00

标签: c++ gcc assignment-operator

让我们从这个小例子开始:

#include <vector>
#include <iostream>

using namespace std;

class A {
private:
    A& operator =(const A&);
};

int main(void) {
    vector<A> v;
    v = { A() };
    return 0;
}

此代码的编译失败,错误消息为error: ‘A& A::operator=(const A&)’ is private。我不知道为什么它需要赋值运算符所以我试图找出并将代码更改为:

#include <vector>
#include <iostream>

using namespace std;

class A {
public:
    A& operator =(const A& a) { cout << "operator=" << endl; return *this; }
};

int main(void) {
    vector<A> v;
    v = { A() };
    return 0;
}

现在代码编译但是当我执行它时它不会在赋值运算符实现中输出调试消息。

所以编译器想要赋值运算符但是没有使用它?我想编译器会以某种方式优化分配。就像它优化了移动构造函数的使用一样(可以通过选项-no-elide-constructors来防止)。是否有可以阻止分配优化的编译器选项?或者是否有不同的解释为什么编译器想要一个可访问的赋值运算符但是在运行时没有使用它?

2 个答案:

答案 0 :(得分:1)

在C ++ 03中,存储在容器中的类型需要是CopyConstructibleAssignable。在C ++ 11中,需求被放宽并应用于在容器上执行的操作。

class A需要CopyConstructibleAssignable,因为存储在vector这就是您需要公开的原因operator=

int main(void) {
    vector<A> v;
    v = { A() }; // Copy Constructor

    A x;
    x = v[0]; // operator=
    return 0;
}

答案 1 :(得分:0)

我迟到了一点,但我仍然想回答你的问题。

您的示例显示了标准的C ++ copy elisionin another question也对此进行了讨论。

也就是说,编译器检查操作的正确性。您必须在默认构造函数之后立即调用 copy构造函数,以使用vector并将类放入内部,但仅调用默认构造函数才能提高性能。

C ++ 11通过move constructor解决了这个问题。