当赋值运算符重载时,const类成员是否有用?

时间:2012-01-16 07:41:52

标签: c++

我有一个类,其成员不会被类的方法更改,因此我将其标记为const。我的问题是我使用默认赋值运算符就像复制构造函数一样,以避免多个声明。但在这种情况下,赋值运算符不会自动生成,因此我得到一些编译器错误: 'operator =' function is unavailable。这似乎没有真正的生活场景,其中可以实际使用const类成员(例如,你在STL代码中看到过任何const成员吗?)。

除了删除const之外,有没有办法解决这个问题?

编辑:一些代码

class A
{
public :
   const int size;
   A(const char* str) : size(strlen(str)) {}
   A() : size(0) {}
};


A create(const char* param)
{
    return A(param);
}


void myMethod()
{
    A a;

    a = create("abcdef");
    // do something

    a = create("xyz");
    // do something
}

4 个答案:

答案 0 :(得分:3)

这是导致此问题的误解:

  

[..]没有被类

的方法改变

成员变量 由您的类(赋值运算符)的方法更改。包括由编译器合成的一个。如果将成员变量标记为const,则表示此变量将(不应该!)在对象的生命周期内更改其值。很明显,为对象分配新值违反了此声明。因此,如果您确实不希望成员更改,请不要将其const

答案 1 :(得分:2)

const成员在许多情况下都是理想的。当然,有一个明显的情况是值不应该或不能改变,但它也是优化和并发的一个重要限制 - 不是每个类型都需要或应该有赋值运算符。

如果成员需要赋值行为,则该变量不能是const

当值/成员不能变异或被this变异时,为变量成员提供单独的接口(甚至更复杂情况下的子类型>组合)更清楚:

class t_text {
public:
// ...
public:
    void setString(const std::string& p);
private:
    const t_text_attributes d_attributes;
    std::string d_string;
};

因此,我的建议是隐藏赋值运算符,并使'mutable chunk'或成员可以设置为清晰:

text.setString("TEXT"); // << Good: What you read is what happens.
text = otherText; // << Bad: Surprise - attributes don't actually change!

答案 2 :(得分:2)

您不能拥有const成员和支持作业,至少不能 具有预期语义的赋值。从逻辑上讲,const是一个 承诺会员永远不会改变,并且任务是 (隐含地,在大多数人的心目中)所有数据的承诺 成员将采用右侧成员的价值观 (通常意味着改变)。有一个非常明确的冲突 在这两个承诺之间。

当然,很多类型不应该支持任务开始; 对于不支持赋值的类型,声明a没有问题 数据成员const。但总的来说,我发现const很多 在这里不太有用; const是合同的一部分,数据成员是 通常不是该类外部合同的一部分。 (但很多 取决于 - 如果数据成员是公共的或受保护的,那么事实 它是不可变的可能是外部合同的一部分。并且 当然,表达内部类不变量没有错 在语言结构中,要么。)

答案 3 :(得分:1)

是的,您可以覆盖赋值运算符。

因为您使用的是默认值,编译器也会尝试复制const成员。这是非法的,因为它是const

class A
{
private:
   const int a;
public :
   A() : a(0) {}
   A& operator = (const A& other) {return *this;}
};

int main()
{
   A a;
   A b;
   a = b; //this is legal if operator = is declared
}