我使用过的所有C++运算符都会返回某些东西,例如+
运算符返回加法的结果。
所有C++运算符都会返回某些东西,还是有一些C++运算符不返回任何东西?
虽然它们可能不是您想象中的运算符,但请注意,delete
和delete[]
C++“关键字”实际上是运算符;并且它们被定义为具有void
返回类型-这意味着它们计算为无效(这不是“something”)。
来自cppreference:
void operator delete ( void* ptr ) noexcept;
void operator delete[]( void* ptr ) noexcept;
delete
表示删除单个对象,delete[]
表示删除对象数组,throw
表示抛出异常,(void)x;
强制转换类型为void
,逗号操作符的左侧是执行表达式而无返回结果,右侧是返回void
的表达式,当使用throw
作为其中一个分支时,?:
三元运算符会抛出异常,dfri的operator void()
(用户定义类型)和眠りネロク的void operator()()
(用户定义类型)。 - Eljaydelete
运算符会销毁对象,然后调用 operator delete
,这一点也让人感到困惑。因此,delete
运算符和 operator delete
是两个不同的东西 :( - Mooing Duckdelete *expression*
会销毁对象,然后调用operator delete
。 - NathanOliverdelete
和delete[]
运算符需要有东西可以操作(一个操作数):即由new
或new[]
运算符分配的内存指针。 - Adrian Mole自定义类型的运算符可以被重载,以执行最奇怪的操作。
例如,+ 运算符会返回加法的结果。
但不一定如此:
#include <iostream>
struct foo {
int value = 0;
void operator+(int x) {
value += x;
}
};
int main () {
foo f;
f + 3;
}
这里的operator+
将左侧加到了value
成员中,其返回类型为void。这是一个虚构的例子,但通常从自定义运算符中不返回任何东西并不罕见。
我所知道的唯一需要返回值的可以进行重载的运算符是operator->
。它必须返回一个原始指针或具有operator->
的对象。
operator->
有些特殊,需要返回指针或者具有operator->
的对象,不确定是否还有其他例外。 - 463035818_is_not_a_numberoperator*(Matrix const& left, Matrix const& right)
返回的不是Matrix
,而是MatrixMul
,因此如果将其输入到operator+(Matrix const& left, MatrixMul const& right)
中,该操作可以是融合乘加运算,这比先乘后加更有效率。 - Matthieu M.operator->
的事情是相关的,也许我会加上它。 - 463035818_is_not_a_number<<
和 >>
被重载为 I/O 操作时,它们应该返回流以便你可以级联它们:stream << foo << bar;
- Barmarvoid
(因此不会评估为任何值)。有些很明显,有些则不是那么明显。一个好的例子是:throw std::runtime_error()
throw
是C++语法中的一个表达式。您可以在其他表达式中使用它,例如条件表达式。
return goodStatus() ? getValue() : throw std::runtime_error();
throw表达式的类型是void
。显然,由于它只会导致执行迅速转移到其他地方,该表达式没有值。
所有内置的C++运算符都不会返回任何东西。重载的C++运算符之所以能够返回值,是因为运算符表示法是对一个函数调用的语法糖。
相反,所有运算符都求值得到一个具有明确定义的值和类型的结果。甚至函数调用运算符void operator()(/*params*/)
也是一个void
类型。
例如,+'a'
是一个int
类型,其值为在你的平台上编码的'a'
字符的值。
如果你的问题是“C++运算符可以有void
返回类型吗?”,那么答案肯定是可以的。
I++
不返回值。如果i
的类型是用户自定义类型,该表达式将被实现为operator++
,它是一个返回值的函数。你称之为“语法糖”,我认为这是一个有重要影响的区别。 - Pete Beckerstruct Task {
void operator()() const;
};
您可以定义特殊的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()
语法来调用它。
我假设你是在谈论运算符函数,而不是语言中作为语法单元的运算符。
如果你在任何类型上重载运算符,你实际上可以返回任何你想要的东西。
这也很有道理,因为像*或()这样的操作有时候直观地不会返回它们的输入类型。想象一下将一个复数类型乘以一个实数类型,或者一个返回集合中某个元素的运算符。
你也可以重载++和--运算符以不返回任何东西,从而消除标准版本极易出错的副作用和表达式值混合的问题。
不。 考虑这两个例子:
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函数不返回实际值。
C++运算符是否返回值取决于您如何使用它们。内置的C++运算符会返回一些值,除非强制返回void。
+=
返回void
,但这并不推荐。此外,函数调用运算符也可以返回void
,这是合法的。 - Mircea Ispas