You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

含const成员的类为何可拷贝/移动?解惑Abseil Tips 177表述

带const成员的类:构造与赋值的关键区别

具体来说,若类包含const成员,则无法对其进行赋值(无论是拷贝赋值还是移动赋值)。C++语言对此的处理是:若类型存在const成员,编译器不会合成拷贝赋值和移动赋值运算符。

我编写了一段C++代码,发现类对象可以被拷贝和移动,请问应如何理解这段表述?

代码如下:

#include <iostream>
class Stitch {
 public:
  Stitch(int in):num(in) { std::cout << "c'tor, address:" << this << std::endl; }
  ~Stitch() { std::cout << "d'tor, address:" << this << std::endl; }
  const int num;
  const std::size_t kAddr = (int)(this);
};
int main() {
  Stitch s1(1);
  std::cout << "s1 address: " << &s1 << " " << s1.num << std::endl;
  Stitch s2 = s1;
  std::cout << "s2 address: " << &s2 << " " << s2.num <<  std::endl;
  Stitch s3 = std::move(s1);
  std::cout << "s3 address: " << &s3 << " " << s3.num <<  std::endl;
  Stitch s4 = Stitch(4);
  std::cout << "s4 address: " << &s4 << " " << s4.num <<  std::endl;
}

你混淆了对象构造和对象赋值的概念,这是理解这段表述的核心:

  • 你的代码里的操作都是构造新对象:

    • Stitch s2 = s1; 是调用拷贝构造函数,用已存在的s1初始化新对象s2,不属于赋值操作。
    • Stitch s3 = std::move(s1); 本质也是构造(因你自定义了析构函数,C++会抑制移动构造的合成,实际调用的是拷贝构造),同样不是赋值。
    • Stitch s4 = Stitch(4); 是用临时对象初始化s4,属于拷贝/移动构造范畴(C++17后会优化为直接构造)。
  • 那段表述针对的是赋值操作:
    当你尝试对已存在的对象进行赋值时,比如写s2 = s1;或s2 = std::move(s1);,编译器会报错——因为类包含const成员,编译器不会自动合成拷贝赋值运算符和移动赋值运算符,而你也没有手动定义这些运算符。

const成员的特性是初始化后无法修改,赋值操作本质是要修改对象的成员(包括const成员),这违反了const的语义,所以编译器不会合成这类运算符;但构造是初始化新对象,const成员可以在初始化阶段设置值,因此不受影响。


内容的提问来源于stack exchange,提问作者Biear

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 20:55:30