Все ли операторы C ++ что-то возвращают?

83

Все операторы C ++, с которыми я работал, что-то возвращают, например + оператор возвращает результат сложения.

Все ли операторы C ++ что-то возвращают, или есть некоторые операторы C ++, которые ничего не возвращают?

user8240761
источник
7
Это зависит от того, насколько узко вы определяете термин «оператор».
molbdnilo
12
Это не предусмотрено стандартом - например, вы можете реализовать +=возврат void, но это не рекомендуется. Также могут возвращаться операторы вызова функций, voidи это действительно так
Мирча Испас
Хм. У меня есть подозрение, что оператор разрешения области ::ничего не возвращает, но мне нужно проконсультироваться со стандартом, чтобы убедиться.
Yksisarvinen
2
Является ли контекст вопроса только типами, предоставляемыми C ++, или он также включает типы, определяемые пользователем?
Eljay
@Eljay Только типы, предоставляемые C ++.
user8240761

Ответы:

112

Нет, не все операторы что-то возвращают.

Хотя они, вероятно, не совсем то, о чем вы думаете, обратите внимание, что ключевые слова deleteи delete[]C ++ на самом деле являются операторами ; и они определены как имеющие voidвозвращаемый тип - что означает, что они ничего не оценивают (что не является «чем-то»).

Из cppreference :

void operator delete  ( void* ptr ) noexcept;
void operator delete[]( void* ptr ) noexcept;
Адриан Моул
источник
13
Мне нравится ваш ответ, он заставил меня иначе задуматься над вопросом. delete, delete[], throw, (void)x;Литье, левая сторона ,оператора, с правой стороны ,оператора , что дает void, А ?:тройная , который использует throwдля одного из плеч, dfri в operator void()(который был бы определяется пользователем),眠りネロク's void operator()()(определенный который был бы пользователь).
Eljay
10
Также сбивает с толку то, что deleteоператор уничтожает объект, а затем вызывает operator delete. Ergo, deleteоператор и operator delete- это разные вещи :( stackoverflow.com/a/8918942/845092
Mooing Duck
7
Не уверен, почему вы ссылаетесь на функции удаления, говоря об операторе удаления. Но все равно.
Дедупликатор
4
@MooingDuck Выражение удаления уничтожает объект, а затем вызывает operator delete.
NathanOliver 02 июл.2020,
Считается ли удаление как оператор, я думал, что объект - это то, что действует на переданный объект? Для работы Delete не нужно передавать или создавать какие-либо объекты ..... Так же, как printf ...
Юнфэй Чен
82

Операторы настраиваемых типов могут быть перегружены для выполнения самых странных вещей.

например, оператор + возвращает результат сложения.

Не обязательно:

#include <iostream>
struct foo {
    int value = 0;
    void operator+(int x) {
        value += x;
    }
};

int main () {
    foo f;
    f + 3;
}

Здесь operator+к valueчлену добавляется левая часть , и его возвращаемый тип недействителен. Это выдуманный пример, но, в целом, отсутствие возврата чего-либо из пользовательского оператора не является чем-то необычным.

Единственный оператор, который может быть перегружен и который требует возврата чего-либо, о чем я знаю, - это operator->. Он должен возвращать необработанный указатель или объект с расширением operator->.

Крупнейший_прайм_ис_463035818
источник
Как ни странно, на самом деле нет ограничений на возвращаемое значение перегруженных операторов. Итак, операторы могут возвращать все, что захотите. en.cppreference.com/w/cpp/language/operators
bracco23 01
5
@ braccor23 operator->немного особенный и должен возвращать либо указатель, либо объект, у которого есть operator->, не уверен, есть ли другие исключения
large_prime_is_463035818 01
1
Да, это единственное ограничение. Даже bool для операторов сравнения. Это выглядит очень странно.
bracco23 01
9
@ idclev463035818: Возможно, более полезным примером могут быть шаблоны выражений. Например, вы можете создать библиотеку матриц, в которой operator*(Matrix const& left, Matrix const& right)не возвращается, Matrixа вместо этого MatrixMul, так что если она затем operator+(Matrix const& left, MatrixMul const& right)вводится в операцию, это может быть объединенное умножение-сложение, которое более эффективно, чем сначала умножение, а затем добавление.
Matthieu M.
1
@DarrelHoffman Когда <<и >>перегружены для операций ввода-вывода, ожидается, что они вернут поток, чтобы вы могли их каскадировать:stream << foo << bar;
Бармар
34

К мелочам операторы ничего не возвращают. Это просто лексические элементы, которые мы используем для создания выражений в языке. Теперь выражения имеют типы и могут оцениваться в значения, и я предполагаю, что это то, что вы подразумеваете под операторами, «возвращающими вещи».

И, ну да. Существуют выражения C ++ с типом void(и, следовательно, не имеют никакого значения). Некоторые из них очевидны, другие - менее. Хорошим примером будет

throw std::runtime_error()

throwэто выражение согласно грамматике C ++. Вы можете использовать его в других выражениях, например, в условном выражении

return goodStatus() ? getValue() : throw std::runtime_error();

А тип выражения throw - void. Очевидно, поскольку это просто приводит к быстрому перемещению выполнения в другое место, выражение не имеет значения.

Рассказчик - Незеленка Моника
источник
21

Ни один из встроенных операторов C ++ ничего не возвращает . Перегруженные операторы C ++ возвращают что-то, поскольку нотация оператора является синтаксическим сахаром для вызова функции.

Скорее, все операторы что-то оценивают . У этого чего-то есть четко определенное значение, а также тип . Даже оператор вызова функции void operator()(/*params*/)является voidтипом.

Например, +'a'это intтип со значением, 'a'закодированным на вашей платформе.

Если ваш вопрос: «Могут ли операторы C ++ иметь voidвозвращаемый тип?» тогда ответ, безусловно, да.

Вирсавия
источник
14
@ idclev463035818: У меня проблема с возвратом . Единственное, что возвращает в C ++, - это функция. Выражения что-то оценивают .
Вирсавия
7
операторы типов классов - это методы, которые что-то возвращают
large_prime_is_463035818
4
Это важный момент. Небрежная терминология приводит к путанице. +1.
Pete Becker
3
@supercat - ваш комментарий злословит кучу трудолюбивых людей, включая меня. Те из нас, кто написал стандарт, никогда не ожидали, что авторы компилятора заполнят детали, опросив другие компиляторы, нынешние или прошлые. Целью стандарта было и является четкое определение синтаксиса и семантики языка программирования C ++. Да, результат не идеален; В последнем стандарте решено множество проблем, которые не решались в более ранних версиях. Это исходит из опыта, осознания осложнений, которых в то время просто не было.
Pete Becker
3
@ Peter-ReinstateMonica - вот более сильная версия. Выражение I++не возвращает значения. Если тип iявляется определяемым пользователем типом, это выражение реализуется как operator++функция, возвращающая значение. Вы называете это «синтаксическим сахаром»; Я называю это различием, имеющим важные последствия.
Pete Becker
12

Фактически вы можете определить оператор вызова функции, чтобы ничего не возвращать. Например:

struct Task {
   void operator()() const;
};
ロ ー ウ
источник
17
Вы можете определить почти любой оператор, чтобы он ничего не возвращал (и столкнулся с гневом разъяренной толпы, которой придется поддерживать этот код)
Yksisarvinen
7
@Yksisarvinen, но, по крайней мере, этот потенциально полезен.
Марк Рэнсом
11

operator void (): определяемая пользователем функция преобразования в void

Вы можете определить своеобразно operator void()функцию преобразования, где компилятор будет даже предупредит вас о том , что Tдля voidфункции преобразования никогда не будет использоваться :

#include <iostream>

struct Foo {
    operator void() { std::cout << "Foo::operator void()!"; }
    // warning: conversion function converting 'Foo' to 
    //          'void' will never be used
};
    
int main() {
    Foo f;
    (void)f;            // nothing
    f.operator void();  // Foo::operator void()!
}

в соответствии с [class.conv.fct] / 1

[...] Функция преобразования никогда не используется для преобразования объекта (возможно, квалифицированного cv) в (возможно, квалифицированный cv) объект того же типа (или ссылку на него) в базовый класс (возможно, квалифицированный cv) такого типа (или ссылку на него), или к (возможно , CV-квалифицированным) void. 117

( 117 ) Эти преобразования рассматриваются как стандартные преобразования в целях разрешения перегрузки ([over.best.ics], [over.ics.ref]) и, следовательно, инициализации ([dcl.init]) и явного приведения типов. Преобразование в voidне вызывает никаких функций преобразования ([expr.static.cast]). Даже если они никогда не вызываются напрямую для выполнения преобразования, такие функции преобразования могут быть объявлены и потенциально могут быть достигнуты через вызов функции виртуального преобразования в базовом классе.

Однако, хотя, как показано выше, вы все равно можете вызывать его, используя явный .operator void()синтаксис.

дфриб
источник
4

Операторы, определенные (встроенные) языком, являются токенами, используемыми для выполнения различных видов вычислений:

  • арифметика (+, -, *, /)
  • приращение / уменьшение (++, -)
  • присвоение (=, + =, - =, * =, / =,% =, >> =, << =, & =, ^ =, | =)
  • логика (!, &&, ||)
  • реляционные (==,! =,>, <,> =, <=)
  • условно?
  • запятая

и так далее. Список может быть очень обширным.

В языковых ссылках, подобных этому или этому , они не обязательно упоминаются как возвращающие что-то, а просто выполнение арифметической или логической операции. , сравнения, с помощью которых переменная может быть изменена, и т. Д.

Поскольку эта операция приводит к некоторому значению, оно может быть интерпретировано как «возвращенное» оператором, но оно отличается от значения, возвращаемого функцией.

С другой стороны, перегруженные операторы могут быть определены с возвращаемым значением некоторого типа, даже если оно может быть недействительным, поэтому нет, не все операторы возвращают какое-либо значение в C ++.

ram0nvaldez
источник
3

Я предполагаю, что вы говорите о операторных функциях, а не об операторах как синтаксической единице языка.

Если вы перегружаете операторы любого типа, вы можете вернуть все, что захотите.

Это также имеет большой смысл, потому что такие операции, как * или (), иногда могут интуитивно не возвращать свой тип ввода. Представьте себе умножение типа комплексного числа на тип действительного числа. Или оператор, возвращающий элемент из коллекции.

Вы также можете перегрузить операторы ++ и -, чтобы ничего не возвращать, тем самым устраняя чрезвычайно подверженное ошибкам смешение побочного эффекта и значения выражения, которое имеет стандартная версия.

Кафеин
источник
2

Нет. Рассмотрим эти два примера здесь:

int multiply (int a, int b) {
   return a*b;
}

void multiply_void(int a, int b) {
   cout << a*b;
//or cout << multiply(a,b);
}

Первая функция вернет целочисленное значение, которое может использоваться другой функцией. Значение возвращается и сохраняется в памяти для использования при необходимости. В противном случае он не виден человеку и просто радостно хранится в памяти.

Вторая функция будет выводить на устройство вывода по умолчанию (обычно консоль). Значение, возвращаемое оператором умножения, передается на устройство вывода. Функция multiply_void не возвращает фактического значения.

Гохан Дилек
источник
0

Все операторы что-то возвращают. Их называют операторами, потому что они чем-то управляют, поэтому они что-то возвращают. Те Операторы, которые что-то не возвращают, не могут называться операторами. Либо они вернут какое-то значение, либо вернут True или False в зависимости от ситуации.

Алби
источник
0

Операторы сами по себе ничего не возвращают. Вызов функций возвращает значения. Операторы могут приводить к значениям. Иногда операторы могут вызывать функции. Примеры включают:

• Оператор вызова функции.

• Перегруженный оператор, который преобразуется в вызов функции.

• оператор new, который вызывается как часть выражения new , является вызовом функции.

Моя единственная цель при упоминании вызовов функций - уточнить результат по сравнению с возвратом. Если посмотреть на все 126 экземпляров «return» и слова, производные от него в [expr] , в этом разделе, кажется, тщательно используется слово return для обозначения:

• результат вызова функции

• аспекты потока управления, связанные с сопрограммами

Ладно, хватит педантизма по поводу результата и возврата.

Саддам Камаль
источник
0

Операторы C ++ возвращают что-то или нет, зависит от того, как вы их использовали. Встроенные операторы C ++ возвращают некоторое значение до тех пор, пока не будут принудительно возвращены void.


источник