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

为何Lambda中声明为const的指针指向会发生变化?

问题:Lambda回调在swap后输出不符合预期的原因

代码示例

#include <iostream>

struct A {
  int i;
};

class AProxy {
 private:
  A* const m_stored;
 public:
  AProxy(A& stored) : m_stored(&stored) {}
  void print() { std::cout << "i is " << m_stored->i << std::endl; }
};

class Holder {
 private:
  A& m_stored1;
  A& m_stored2;

 public:
  Holder(A& stored1, A& stored2) : m_stored1(stored1), m_stored2(stored2) {}
  void print() {
    std::cout << "i is " << m_stored1.i << std::endl;
  }
  void swap() {
    std::swap(m_stored1, m_stored2);
  }
  AProxy getstored1() { return {m_stored1}; }
  AProxy getstored2() { return {m_stored2}; }
};


int main() {
  A foo;
  A bar;
  foo.i = 5;
  bar.i = 6;

  Holder holder = {foo, bar};

  AProxy fooproxy = holder.getstored1();
  AProxy barproxy = holder.getstored2();

  auto foofunc = [fooproxy]() {
    AProxy copy = {fooproxy};
    copy.print();
  };

  foofunc(); //Prints 5
  holder.swap();
  foofunc(); //Prints 6?

  return 0;
}

疑问

我在AProxy中声明m_stored为指向不可变的const指针,预期它会持续指向foo,但调用holder.swap()后,Lambda中的输出变为了6,这是为什么?

解答

你误解了A* const m_stored的含义,以及Holder::swap()实际做的事情:

  1. A* const m_stored的本质:
    这个声明表示指针变量m_stored本身是不可修改的——也就是说,它一旦指向某个A对象的地址,就不能再指向其他地址。但它指向的对象的内容是可以被修改的,比如对象的i成员变量。

  2. Holder::swap()的实际操作:
    Holder里的m_stored1和m_stored2是A类型的引用,C++中引用一旦绑定到对象就无法改变指向。当你调用std::swap(m_stored1, m_stored2)时,std::swap并没有交换引用的指向,而是交换了两个引用所指向的对象的全部内容——也就是把foo和bar的i值(以及A的所有成员)做了交换。

  3. 为什么输出会变6:
    你的fooproxy里的m_stored确实一直指向foo对象的地址,但调用holder.swap()后,foo对象的i值已经被换成了原来bar的6,而bar的i值变成了5。Lambda捕获的fooproxy副本依然指向foo,所以第二次调用foofunc()时,打印的是foo现在的i值6。

如果想要验证这个结论,可以在holder.swap()之后加上两行打印:

std::cout << "foo.i = " << foo.i << std::endl;
std::cout << "bar.i = " << bar.i << std::endl;

你会看到输出是foo.i = 6和bar.i = 5,这就直接证明了对象内容被交换,而指针指向的地址并没有变。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 22:02:01