在 C++ 中,具有 const 数据成员的 class 可以没有复制赋值运算符吗?
In C++, can a class with a const data member not have a copy assignment operator?
我正在设计一个 class,它应该有一个名为 K
的常量数据成员。我还希望这个 class 有一个复制赋值运算符,但编译器似乎隐式地从任何具有 const 数据成员的 class 中删除了复制赋值运算符。这段代码说明了本质问题:
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.
我想我明白为什么编译器会这样做;我要复制到的 class 的实例必须存在才能复制到,如果它是常量,我不能在该目标实例中分配给 K
,因为我是试图做上面的事情。
我对这个问题的理解正确吗?如果是这样,有没有办法解决这个问题?也就是说,我可以为我的 class 定义一个复制构造函数并仍然提供 K
类似 const 的保护吗?
在 C++ 中,具有 const
数据成员的 class 可能具有复制构造函数。
#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 不能使用默认赋值运算符。
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
数据成员的 class 可以使用非默认赋值运算符,只要您不尝试更改 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;
}
不会产生编译时错误。
从 c++20 开始,您现在可以通过定义自己的 copy-assignment 运算符来复制具有一个或多个 const 成员对象的对象。
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);
}
}
};
这是通过 basic.life 中的更改实现的,它允许透明替换对象,包括包含 const sub-objects、w/o UB 的对象。
我正在设计一个 class,它应该有一个名为 K
的常量数据成员。我还希望这个 class 有一个复制赋值运算符,但编译器似乎隐式地从任何具有 const 数据成员的 class 中删除了复制赋值运算符。这段代码说明了本质问题:
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.
我想我明白为什么编译器会这样做;我要复制到的 class 的实例必须存在才能复制到,如果它是常量,我不能在该目标实例中分配给 K
,因为我是试图做上面的事情。
我对这个问题的理解正确吗?如果是这样,有没有办法解决这个问题?也就是说,我可以为我的 class 定义一个复制构造函数并仍然提供 K
类似 const 的保护吗?
在 C++ 中,具有 const
数据成员的 class 可能具有复制构造函数。
#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 不能使用默认赋值运算符。
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
数据成员的 class 可以使用非默认赋值运算符,只要您不尝试更改 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;
}
不会产生编译时错误。
从 c++20 开始,您现在可以通过定义自己的 copy-assignment 运算符来复制具有一个或多个 const 成员对象的对象。
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);
}
}
};
这是通过 basic.life 中的更改实现的,它允许透明替换对象,包括包含 const sub-objects、w/o UB 的对象。