【问题标题】:What is the name of this C++ functionality?这个 C++ 功能的名称是什么?
【发布时间】:2015-01-15 11:40:01
【问题描述】:

我正在编写一些 C++ 代码并错误地省略了函数名称WSASocket。但是,我的编译器没有引发错误,并将我的 SOCKET 与整数值 1 相关联,而不是有效的套接字。

有问题的代码应该是这样的:

this->listener = WSASocket(address->ai_family, address->ai_socktype, address->ai_protocol, NULL, NULL, WSA_FLAG_OVERLAPPED);

但是,它看起来像这样:

this->listener = (address->ai_family, address->ai_socktype, address->ai_protocol, NULL, NULL, WSA_FLAG_OVERLAPPED);

来自其他语言,这个看起来可能是某种匿名类型。该功能的名称是什么,如果它真的是一个功能?

它的目的是什么?

当您不知道从哪里开始时,很难搜索它。

【问题讨论】:

  • +1,酒吧测验的好问题(对于喜欢雇用擅长脑筋急转弯的人的公司来说,这是一个骇人听闻的面试问题)。
  • 链接到Wikipedia article on comma operator。 FWIW,常见用途之一是在for 循环中获得两个副作用 *迭代表达式, ala for (int i = 0, j = 0; i
  • @MichaelJ.Gray 从技术上讲你错了。它不会覆盖行为。想象一下:i=0;j=0;x=i++,j=6; x 和 j 将是 6,而 i 无论如何都会是 1。如果 i++ 的行为将被覆盖,它将保持为 0。但是每个语句都会被调用,并且在达到 , 之后,所有扩展都会被丢弃,并且下一个伪序列点被调用。所以第一个= 只是分配最后一个, 之后的部分,但每个点都会被调用。无论如何:我不明白为什么您的编译器不会在重新定义函数声明时警告您,而是将您的代码更改为不同的行为
  • 如果您使用适当的编译器,并打开警告,它会警告此类狡猾的代码,例如 gccg++-Wall 选项说:warning: left-hand operand of comma expression has no effect [-Wunused-value]跨度>
  • 所以,在我看来,这个问题的最佳答案是“始终启用警告”——然后编译器本身会解释存在错误并告诉你你做了什么;这个答案也将为您解决许多其他问题。

标签: c++


【解决方案1】:

逗号运算符†计算左侧,丢弃它的值,结果产生右侧。 WSA_FLAG_OVERLAPPED 为 1,即为表达式的结果;所有其他值都被丢弃。从未创建任何套接字。


† 除非重载。是的,它可以超载。不,你不应该超载它。立即远离键盘!

【讨论】:

  • +1,boost spirit 非常有效地重载了逗号运算符,但这是规则的一个非常孤独的例外:不要这样做
  • @Bathsheba Boost.Assign 也重载了逗号运算符,但自从 C++11 以来谁在使用它?
  • 但你确实对强大的逗号有多可怕有最好的解释。无情且充满嘲讽,它困扰了我的代码几分钟,同时盯着我看,并没有为它的行为感到羞耻。
  • @R.MartinhoFernandes - Eigen 也非常有效地重载了逗号运算符。请参阅this SE question 了解一些示例用法。
【解决方案2】:

逗号操作符可以理解你的代码。

您实际上是在设置 this->listener = WSA_FLAG_OVERLAPPED;,这恰好在语法上是有效的。

【讨论】:

  • 不仅在语法上有效,而且由于 Windows API 不是类型安全的,因此它也是有效的转换。
  • @MSalters 并不是说​​ POSIX 在这方面要好得多
  • 这就是为什么可使用单个参数调用的构造函数应该是显式,然后会发生编译器错误,开发人员将有机会再次查看奇怪的结构。
  • @MSalters 好吧,SOCKETunsigned int 的 typedef,WSA_FLAG_OVERLAPPEDint 文字。如果SOCKETint 的同义词,它甚至不会是转换
  • @Joker_vD:确实。如果他们将其设为struct __socket* 的类型定义,我们的错误就会减少。但是有太多代码“知道”SOCKET 是不可或缺的。
【解决方案3】:

编译器依次计算括号内的每个sequence point,结果是最终表达式,即表达式中的WSA_FLAG_OVERLAPPED

逗号运算符, 是C++ 中的一个序列点。逗号左边的表达式在右边的表达式之前被完全计算。结果始终是右侧的值。当你得到一个 (x1, x2, x3, ..., xn) 形式的表达式时,表达式的结果总是xn

【讨论】:

  • 在您在那里添加说明之后,它更有意义。一开始不太明白序列点问题的相关性。
猜你喜欢
  • 2017-01-07
  • 2016-04-18
  • 1970-01-01
  • 2018-12-19
  • 1970-01-01
  • 2014-10-03
  • 2018-06-04
  • 2011-06-03
  • 2012-03-05
相关资源
最近更新 更多