在C++中,一个有常量数据成员的类可以没有复制赋值运算符吗?

wz8daaqr  于 2023-01-22  发布在  其他
关注(0)|答案(2)|浏览(136)

我正在设计一个类,它应该有一个名为K的常量数据成员,我还希望这个类有一个复制赋值操作符,但是编译器似乎隐式地从任何有常量数据成员的类中删除了复制赋值操作符,下面的代码说明了一个基本问题:

class A
{
    private:
       const int K;
    public:
       A(int k) : K(k) {} // constructor
       A() = delete; // delete default constructor, since we have to set K at initialization

       A & operator=(A const & in) { K = in.K; } // copy assignment operator that generates the error below
}

下面是它生成的错误:

constructor.cpp:13:35: error: cannot assign to non-static data member 'K' with const- 
qualified type 'const int'
            A & operator=(A const & in) { K = in.K; }
                                          ~ ^
constructor.cpp:6:13: note: non-static data member 'K' declared const here
            const int K;
            ~~~~~~~~~~^
1 error generated.

我想我理解编译器为什么要这样做;要复制到的类的示例必须存在,然后才能被复制到,如果它是常量,我就不能在目标示例中赋值给K,正如我在上面尝试做的那样。
我对这个问题的理解是正确的吗?如果是的话,有没有解决这个问题的方法?也就是说,我可以为我的类定义一个复制构造函数,同时仍然给予K类似常量的保护吗?

anauzrmj

anauzrmj1#

    • 在C++中,具有const数据成员的类可能具有复制构造函数。**
#include <iostream>

class A
{
private:
    const int k_;
public:
    A(int k) : k_(k) {}
    A() = delete;
    A(const A& other) : k_(other.k_) {}

    int get_k() const { return k_; }
};

int main(int argc, char** argv)
{
    A a1(5);
    A a2(a1);

    std::cout << "a1.k_ = " << a1.get_k() << "\n";
    std::cout << "a2.k_ = " << a2.get_k() << "\n";
}

输出:

a1.k_ = 5
a2.k_ = 5
    • 在C++中,具有const数据成员的类不能使用默认赋值运算符。**
class A
{
private:
    const int k_;
public:
    A(int k) : k_(k) {}
    A() = delete;
    A(const A& other) : k_(other.k_) {}

    int get_k() const { return k_; }
};

int main(int argc, char** argv)
{
    A a1(5);
    A a2(0);

    a2 = a1;
}

产生编译时错误:

const_copy_constructor.cpp: In function ‘int main(int, char**)’:
const_copy_constructor.cpp:18:10: error: use of deleted function ‘A& A::operator=(const A&)’
   18 |     a2 = a1;
      |          ^~
const_copy_constructor.cpp:1:7: note: ‘A& A::operator=(const A&)’ is implicitly deleted because the default definition would be ill-formed:
    1 | class A
      |       ^
const_copy_constructor.cpp:1:7: error: non-static const member ‘const int A::k_’, can’t use default assignment operator
    • 在C++中,具有const数据成员的类可以使用非默认赋值运算符,只要您不尝试更改const数据成员即可,但您最好仔细考虑一下,如果无法修改某个基础成员,使用此赋值运算符意味着什么。**
class A
{
private:
    const int k_;
public:
    A(int k) : k_(k) {}
    A() = delete;
    A(const A& other) : k_(other.k_) {}

    A& operator=(A const& other)
    {
        // do nothing
        return *this;
    }

    int get_k() const { return k_; }
};

int main(int argc, char** argv)
{
    A a1(5);
    A a2(0);

    a2 = a1;
}

不会产生编译时错误。

tpxzln5u

tpxzln5u2#

从c++20开始,你现在可以通过定义你自己的复制赋值操作符来复制有一个或多个常量成员对象的对象。

class A
{
private:
    const int K;
public:
    A(int k) : K(k) {} // constructor
    A() = delete; // delete default constructor, since we have to set K at initialization
    // valid copy assignment operator in >= c++20
    A& operator=(A const& in) {
        if (this != &in)
        {
            std::destroy_at(this);
            std::construct_at(this, in);
        }
        return *this;
    }
};

这是由于www.example.com中的更改basic.life,允许透明替换对象,包括那些包含常量子对象的对象,w/o UB。

相关问题