【问题标题】:Does swap() cause undefined behaviour?swap() 会导致未定义的行为吗?
【发布时间】:2014-08-11 17:17:06
【问题描述】:

我试图从 [C++11:utility.swap] 中了解std::swap 的条件。模板定义为

template <typename T> void swap(T &, T &)

(加上一些noexcept 细节)并具有“交换存储在两个位置的值”的效果。

以下程序是否定义明确?

#include <utility>

int main()
{
    int m, n;
    std::swap(m, n);
}

如果我自己编写交换代码(即int tmp = m; m = n; n = tmp;),它将具有未定义的行为,因为它会尝试对未初始化的对象进行左值到右值的转换。但是标准的std::swap 函数似乎没有附加任何条件,也不能从规范中得出存在任何左值到右值和UB 的规范。

标准是否要求std::swap 对未初始化的对象执行一些明确定义的魔法?

为了澄清这一点,请考虑函数void f(int &amp; n) { n = 25; },它永远不会有未定义的行为(因为它不是从n 读取的)。

【问题讨论】:

  • 您的程序在调用swap 之前未定义mn。定义它们不是swap 的工作; swap 的两个参数都应该被定义。所以我没有看到问题出在哪里。
  • 好吧,至少对于 C++1y,我肯定会这么说 using and indeterminate int would be undefined。我认为swap 做的任何事情都不会改变这一点。我可能会说 C++11 的意图可能是相同的。唯一的例外是在无符号窄字符的情况下,它会保留其不确定的值。
  • @MikeDeSimone:嗯,这有点不可能实现,正如您从我的示例尝试中看到的那样......它在哪里说“两个参数都应该被定义”?跨度>
  • @ShafikYaghmour:std::swap 也要求库魔法,还是缺少一个条件?
  • @ShafikYaghmour:我不关注...请查看我的更新。问题在呼叫现场没有表现出来; f(a) 完全有效。

标签: c++ c++11 language-lawyer undefined-behavior lvalue-to-rvalue


【解决方案1】:

非常好的问题。但是,我会说 [res.on.arguments]§1 涵盖了这一点:

以下每一项都适用于 C++ 标准库中定义的函数的所有参数,除非 另有明确说明。

  • 如果函数的参数具有无效值(例如函数域之外的值 或指针对其预期用途无效),则行为未定义。

为了解决您对f(n) 的担忧,您问题中的函数f 不是C++ 标准库的一部分,因此上述条款不适用于它。

【讨论】:

  • swap(m, n)f(m) 有何不同?函数参数在这两种情况下都是有效
  • 它没有明确说明,但我同意。
  • C++ 标准库中任何与f(n) 示例类似的函数都将定义一个异常,说明传入的值无关紧要,要么保持不变,要么被覆盖。跨度>
  • 问题是“无效值”没有很好的定义。我怀疑它应该涵盖这样的情况。
  • @KerrekSB 我知道swap 中没有任何指针,但“例如”并不是一个排他性的表述。我的意思是:如果有效指针可以是“无效值”,因为它“对其预期用途无效”,那么未初始化的值也可以是“无效值”。
【解决方案2】:

由于 M 的值未定义,我希望它会污染对交换的调用。 调用 swap 时,鼻魔可能会飞。

【讨论】:

  • 不幸的是,标准文本 ([utility.swap]) 似乎没有提及 T = int 的任何限制或条件。
  • 这没有什么不好的。期望有特定的文档告诉您所有编译器选项的所有函数都会发生什么未定义的行为是不现实的。
  • @EvilTeach:指定如果x 已定义且yswap(x,y) 之前未定义,那么在交换之后x 将未定义且@ 987654326@ 将保留以前的值 x。我不确定当x(或y)未定义时,声明swap(x,y) 必须不可访问会更有用,即使在没有@987654332 的情况下可以访问swap(x,y) @被定义,y的值将被废弃而不被使用。
  • 否则,我会说如果 swap 被指定为使用其一个或两个操作数作为右值,那么在没有指定两个有效右值的情况下调用将是 UB,但在没有这样的规范的情况下,我认为没有理由允许实现将任一操作数作为右值访问除非它可以保证这样做不会导致未定义的行为。
猜你喜欢
  • 2016-09-04
  • 1970-01-01
  • 2013-04-24
  • 1970-01-01
  • 1970-01-01
  • 2016-02-17
  • 2022-11-16
  • 2013-10-02
  • 2015-04-12
相关资源
最近更新 更多