所有C ++运算符都返回什么吗?


83

我使用过的所有C ++运算符都返回某些内容,例如,该+运算符返回加法的结果。

是所有C ++运算符都返回什么,还是有些C ++运算符不返回任何东西?


7
这取决于您对“操作员”一词的定义范围。
molbdnilo

12
这不是标准强制的-例如,您可以实现+=return void,但是不建议这样做。函数调用运算符也可以返回void,这是有效的
Mircea Ispas

嗯 我有一种预感,范围解析运算符::不返回任何内容,但是我必须参考标准来确保。
Yksisarvinen

2
问题的上下文是仅针对C ++提供的类型,还是还包括用户定义的类型?
Eljay

@Eljay仅C ++提供了类型。
user8240761

Answers:


111

不,并非所有操作员都会返回一些东西。

尽管它们可能不完全是您所想的,但请注意,deletedelete[]C ++的“关键字”实际上是运算符;它们被定义为具有void返回类型-它们其中的手段评价到什么(这是不是“东西”)。

来自cppreference

void operator delete  ( void* ptr ) noexcept;
void operator delete[]( void* ptr ) noexcept;

13
我喜欢您的回答,这使我对问题的看法有所不同。 deletedelete[]throw(void)x;铸造,左侧,的操作者,右侧,操作员的收益率void,一个?:一个使用三元throw的臂中的一个,dfri的operator void()(定义这将是用户),眠りネロク的void operator()()(这将是用户定义的)。
Eljay

10
delete操作员先销毁对象然后调用,这也令人困惑operator delete。因此,delete运算符Ergooperator delete是分开的事情:( stackoverflow.com/a/8918942/845092
Mooing Duck

7
不确定在谈论删除操作符时为什么要引用删除功能。但是无所谓。
重复数据删除器

4
@MooingDuck delete表达式销毁对象,然后调用operator delete
NathanOliver

删除是否算作运算符,我以为对象是对传递的对象起作用的东西?删除不需要传递或创建任何对象即可工作.....就像printf .....
Yunfei Chen

82

自定义类型的运算符可以重载以执行最奇怪的事情。

例如,+运算符返回加法的结果。

不必要:

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

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

此处operator+将左侧添加到该value成员,并且其返回类型为void。这是一个虚构的示例,但总的来说,不从自定义运算符返回任何内容并不罕见。

我知道,唯一可以重载并且需要返回某些内容的运算符是operator->。它必须返回原始指针或具有的对象operator->


有趣的是,实际上对重载运算符的返回值没有任何限制。因此,操作员可以退还您想要的任何东西。cn.cppreference.com/w/cpp/language/operators
bracco23

5
@ braccor23operator->有点特殊,它需要返回一个指针或一个对象,该对象具有一个operator->,不确定是否还有其他异常
idclev 463035818

1
是的,那是唯一的约束。比较运算符甚至不满意。看起来真奇怪。
bracco23

9
@ idclev463035818:也许更有用的示例是表达模板。例如,您可以创建一个矩阵库,在其中operator*(Matrix const& left, Matrix const& right)不返回Matrix,而是返回MatrixMul,这样,如果将其馈送到operator+(Matrix const& left, MatrixMul const& right)运算中,则可以进行融合的乘加运算,它比先乘后加运算的效率更高。
Matthieu M.

1
@DarrelHoffman当<<>>被I / O操作重载时,它们将返回流,以便您可以对其进行级联:stream << foo << bar;
Barmar

34

对于nitpick,操作员不返回任何东西。它们只是我们用来创建语言表达的词汇元素。现在,表达式具有类型并且可以求值。我假设这就是运算符“返回事物”的意思。

而且,是的。有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
类类型的运算符是返回某些内容的方法
idclev 463035818

4
这是重要的一点。马虎的术语导致混乱。+1。
皮特·贝克尔

3
@supercat-您的评论使包括我在内的一帮辛勤工作的人屈服。我们这些编写标准的人从未期望过编译器作者会通过轮询当前或过去的其他编译器来填写细节。该标准的目标是并且现在一直是明确定义C ++编程语言的语法和语义。是的,结果并不完美;最新标准中解决了许多问题,而早期版本中未解决。这来自经验,认识到当时根本看不到的并发症。
皮特·贝克尔

3
@ Peter-ReinstateMonica-这是一个更强大的版本。表达式I++不返回值。如果类型i是用户定义的类型,则该表达式将实现为operator++,这是一个返回值的函数。您称其为“语法糖”;我称这种区分具有重要的后果。
皮特·贝克尔

12

您实际上可以定义一个函数调用运算符,以不返回任何内容。例如:

struct Task {
   void operator()() const;
};

17
您可以定义几乎所有运算符都不返回任何值(并面对必须维护该代码的愤怒暴民的愤怒)
Yksisarvinen

7
@Yksisarvinen,但至少这一点可能有用。
Mark Ransom

11

运算符void():用户定义的转换void的函数

您可以定义特殊的operator void()转换函数,编译器甚至会警告您永远不要使用Ttovoid转换函数:

#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-合格) void117

117 这些转换出于过载解析([over.best.ics],[over.ics.ref])以及初始化([dcl.init])和显式强制转换的目的被视为标准转换。到的转换void不会调用任何转换函数([expr.static.cast])。即使从未直接调用过执行转换,也可以声明此类转换函数,并有可能通过对基类中的虚拟转换函数的调用来实现。

但是,如上所述,尽管如此,您仍然可以使用显式.operator void()语法来调用它。


4

由语言定义(内置)的运算符是用于执行各种计算的令牌:

  • 算术(+,-,*,/)
  • 增量/减量(++,-)
  • 赋值(=,+ =,-=,* =,/ =,%=,>> =,<< =,&=,^ =,| =)
  • 逻辑(!,&&,||)
  • 关系(==,!=,>,<,> =,<=)
  • 有条件的?
  • 逗号

等等。该列表可能非常广泛。

在像语言的引用这一个这一个,这些并不一定为返回的东西,只是执行算术运算或逻辑引用操作,通过这意味着变量的比较可以被修改,等

由于此操作会产生某些值,因此可以将其解释为由操作员“返回”,但它不同于函数返回值。

另一方面,可以使用某种类型的返回值来定义重载的运算符,即使该返回值也可以是无效的,因此,不,并非所有运算符都在C ++中返回某些值。


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);
}

第一个函数将返回一个整数值,该值可以被另一个函数使用。该值将返回并存储在内存中,以便在必要时使用。如果不是,则它对人类是不可见的,并且只是快乐地坐在内存中。

第二个功能将输出到默认输出设备(通常是控制台)。乘法运算符返回的值将传递到输出设备。函数multiple_void不返回实际值。


0

所有操作员都返回一些东西。他们之所以称为操作员,是因为他们操作某物,因此他们将返回某物。那些不退货的操作员不能称为操作员。它们要么返回某个值,要么根据情况返回True或False。


0

操作员自己不一定返回任何东西。函数调用返回值。运算符可以产生值。操作员有时可以调用函数。示例包括:

•函数调用运算符。

•重载的运算符,将其转换为函数调用。

•作为new-expression的一部分调用的operator new是函数调用。

我提到函数调用的唯一目的是弄清楚结果与返回。通过查看[expr]中的所有126个“ return”实例及其派生的单词,该节似乎谨慎地使用单词return来指代:

•函数调用的结果

•与协程相关的控制流程的各个方面

好的,这足以说明结果与回报。


0

C ++运算符是否返回某些内容取决于您如何使用它们。内置C ++运算符将返回一些值,直到除非被强制返回void。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.