Як називається ця функціональність С ++?


82

Я писав деякий код на 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);

Виходячи з інших мов, схоже, це може бути якийсь анонімний тип. Як називається об’єкт, якщо це справді об’єкт?

Яка його мета?

Його важко шукати, коли ти не знаєш, з чого почати.


3
+1, приємне запитання для паб-вікторини (або жахливе запитання на співбесіді для фірм, які люблять наймати людей, які добре знають мозку).
Вірсавія,

8
Посилання на статтю Вікіпедії про оператор кома . FWIW, одним із найпоширеніших застосувань є отримання двох побічних ефектів у forвиразі ітерації циклу * , ala для (int i = 0, j = 0; i <10; ++ i, --j) ... `
Тоні Делрой,

1
@ MichaelJ.Gray Технічно Ви помиляєтесь. Це не перезапис поведінки. Уявіть: i=0;j=0;x=i++,j=6;x і j мали б значення 6, а я б у будь-якому випадку 1. Якщо поведінку i ++ було б перезаписано, воно залишалося б 0. Але кожен вираз викликається, а після досягнення ,просто всіх розширень відкидається, а наступна псевдопослідовність отримується. Отже, перший =просто призначає частину після останньої, ,але кожен пункт отримує виклик. У будь-якому випадку: я не розумію, чому ваш компілятор не попереджає вас про перевизначення оголошення функції, а замість цього змінює ваш код на щось
інше

5
Якщо ви використовуєте відповідний компілятор, з попередженнями включені, він буде попереджати про таке сумнівне коді, наприклад , gccі g++з -Wallопцією каже:warning: left-hand operand of comma expression has no effect [-Wunused-value]
Сем Уоткінс

3
Отже, на мій погляд, найкращою відповіддю на це запитання є "завжди вмикати попередження" - тоді сам компілятор пояснить, що є помилка, і скаже, що ви зробили; і ця відповідь також вирішить багато інших проблем для вас.
Сем Уоткінс,

Відповіді:


151

Оператор кома † обчислює ліву сторону, відкидає її значення і в результаті дає праву. WSA_FLAG_OVERLAPPEDдорівнює 1, і це результат виразу; всі інші значення відкидаються. Жодна розетка ніколи не створюється.


† Якщо не перевантажений. Так, його можна перевантажити. Ні, не слід його перевантажувати. Відійдіть від клавіатури, прямо зараз!


9
+1, підняття духу дуже ефективно перевантажує оператор-кома, але це дуже самотній виняток із правила: не роби цього .
Вірсавія,

2
@Bathsheba Boost. Призначення також перевантажує оператор кома, але хто використовує це з C ++ 11?
rubenvb

39
Але ти мав найкраще пояснення, якою жахливою може бути могутня кома. Невибачливий і повний глузувань, він мучив мій код кілька хвилин, дивлячись на мене без сорому за свою поведінку.
Michael J. Gray


1
@ R.MartinhoFernandes - Eigen також дуже ефективно перевантажує оператор коми. Див. Це запитання про SE для ознайомлення з деякими зразками.
Девід Хаммен,

22

Оператор- кома осмислює ваш код.

Ви фактично встановлюєте, this->listener = WSA_FLAG_OVERLAPPED;що саме є синтаксично допустимим.


3
Не тільки синтаксично допустимий, але оскільки API Windows не є безпечним для типу, він також є допустимим перетворенням.
MSalters

5
@MSalters не те, що POSIX набагато кращий у цьому відношенні
chbaker0

1
Ось чому конструктори, що викликаються одним аргументом, повинні бути явними , тоді б сталася помилка компілятора, і розробник мав би шанс поглянути на цю химерну конструкцію вдруге.
Matthieu M.

@MSalters Ну, SOCKETце typedef для unsigned intі WSA_FLAG_OVERLAPPEDє літералом int. Якби це SOCKETбуло синонімом int, це навіть не було б перетворенням .
Joker_vD

1
@Joker_vD: Дійсно. Якби вони зробили це typedef для struct __socket*, у нас було б менше помилок. Але там занадто багато коду, який "знає" SOCKETє невід'ємною частиною.
MSalters

21

Компілятор по черзі обчислює кожну точку послідовності в дужках, і результат є кінцевим виразом WSA_FLAG_OVERLAPPEDу виразі.

Оператор кома ,- це точка послідовності в C ++. Вираз ліворуч від коми повністю обчислюється перед виразом праворуч. Результатом завжди є значення праворуч. Коли у вас є вираз форми (x1, x2, x3, ..., xn), результат виразу завжди xn.


Після того, як ви додали туди своє роз’яснення, це має більше сенсу. Спочатку я не зовсім розумів актуальність проблеми точки послідовності.
Michael J. Gray
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.