【问题标题】:Under what conditions does C++ optimize out constructor calls?C++ 在什么条件下优化构造函数调用?
【发布时间】:2012-03-04 10:18:39
【问题描述】:

我正在为矩阵算术编写一个类,我正在实现的一个功能是您可以“切片”一个矩阵并获取另一个矩阵,但这样做是为了让返回的矩阵引用父级的内存。如果您想要获取矩阵的子部分或将向量添加到列或类似的事情,这非常有用。

但是,我想实现它,这样如果返回的矩阵被分配或复制,别名就会被破坏并复制内存,这样你就不能轻易地永远传递一个别名矩阵。

在玩这个时,我有这样的事情:

matrix B = A.slice(1,1);  

A.slice(1,1) 返回 A 的子矩阵(偏移 1 行和 1 列)。我实现了 = 运算符来打破别名,但令我懊恼的是,即使打开 -O0 也不会在执行此操作时调用它。同样:

matrix B(A.slice(1,1)); 

不调用复制构造函数(也是为了中断别名而编写的)。唯一有效的是:

matrix B; B = A.slice(1,1);

我的问题是,很明显,因为我在前两个示例中直接从 A 初始化 B,所以它采取了某种捷径,而我在最后一个示例中首先显式创建 B,然后 然后 分配A.slice(1,1) 到它。

有人可以告诉我在调用复制构造函数和赋值运算符时的规则吗?

【问题讨论】:

  • 您是否尝试过使用调试器单步执行代码?如果是这样,前两个示例的名称是什么?在这两种情况下,我都希望复制构造函数......
  • 另外,您是否返回了对 Matrix 的 const 引用?如果没有,我会推荐它。
  • @BenHocking:我不建议返回对临时对象的引用。
  • 我尝试单步执行代码,我的 Matrix::slice 方法使用私有构造函数直接构建并返回别名矩阵,这是我看到的唯一调用的构造函数。没有复制构造函数或赋值运算符。

标签: c++


【解决方案1】:

这称为复制省略,或返回值优化(C++11 标准的§12.8.31)。几乎任何返回类类型的函数都可以跳过复制构造函数。这通常与返回类类型的实际实现密切相关。 (请注意,您也有点依赖这个:大概slice 按值返回您的矩阵类型,如果它会破坏您的别名,您不希望在那里调用复制构造函数。)

您很可能需要以其他方式实现这一点——例如,slice 返回某种代理类型,该类型支持相同的操作并且可以转换为您的正常矩阵类型,从而在转换过程中中断别名。

【讨论】:

  • 你知道我是否可以依靠复制省略行为,或者它是否是 C++ 标准所要求的(我在这里没有使用 C++11)。你是对的,如果它不是我可以指望的东西,那么当没有复制省略时,按值返回将复制并破坏别名,但在有复制省略时不会......
  • 不,你不能指望它,除非你的编译器证明它总是会发生。从技术上讲,这是一种可选的优化。但它很可能总是用于一步返回,因为它与实现相关(足够大的类往往会通过传递一个指向存储的指针并在那里构造它来返回),但构造函数之间有两个或多个级别并且最终使用几乎肯定会因编译器和优化设置而异。
  • 好的,我得考虑一下如何实现它。
猜你喜欢
  • 2013-05-22
  • 1970-01-01
  • 1970-01-01
  • 2013-06-21
  • 2020-11-15
  • 1970-01-01
  • 2020-10-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多