C++中运算符和函数的区别?

15

我需要帮助理解以下C++的内容,特别是运算符和函数之间的区别:

  • 什么是运算符?
  • 什么是函数?
  • 它们之间有什么区别?
  • 用户定义的operator+()是一个函数还是一个运算符
  • 运算符是否可以在编译时操作操作数?它们总是在编译时操作吗?(像C++中的sizeof()一样)
8个回答

14

运算符是类似于+-+=等符号(见13.5)。它们本身没有意义。在语义分析期间,会确定运算符的含义。

函数是构造函数、析构函数、转换函数(看起来像operator type())或者运算符函数(函数模板特化和实例化可以反过来产生它们)。

运算符函数是用来实现运算符的东西(参见13.5)。例如,operator+就是一个例子。它们在所有方面都是函数,与“常规”的函数唯一的区别是它们可能会被隐式调用,并且有一个奇怪的名称。

某些运算符具有内置含义,可以由程序员更改。提到一个运算符的内置含义时,只需说内置运算符(见5/3)。然而,如果这样的运算符应用于为其定义了内置含义的操作数,则只允许在少数情况下更改该含义(这些情况包括赋值、取地址和逗号运算符,见13.5/6)。


9

什么是操作符?

操作符是用于表达式中的符号。
例如:+ - * / 等等。

对于内置类型,这些操作是明确定义且不可更改的。
对于用户定义的类型,可以将操作符定义为函数/方法调用的语法糖。

Array a;
a = b + c; // a.operator=(b.operator+(c));

什么是函数?

我们大多数时候将函数和方法互换使用。它们的唯一区别在于,方法与类对象实例相关联。否则它们是相同的。它们提供了一种将一组指令分组在一起的方式。

它们之间有什么区别?

运算符对内置类型的操作由编译器定义。
运算符对用户定义的类型的操作是一个函数调用。

用户定义的 operator+() 是函数还是运算符?

它是一个函数(或方法)。对用户定义的类型使用运算符只是语法糖,实际上是一个函数调用。但在正常会话中,它们仍然称为运算符。

运算符能够在编译时操作操作数吗?

对于内置类型是可以的。编译器具有广泛的优化能力。
对于用户定义的类型。它可以像其他函数一样对运算符进行优化,这可能会导致运算符被消除,但代码不会在编译时执行。

它们总是在编译时操作吗?(例如 C++ 中的 sizeof())

不是。sizeof() 相对独特。

编辑:

为了说明用户定义类中的运算符行为就像函数一样,这里有一个使用 mem_fun_ref 的示例:

#include <vector>
#include <algorithm>
#include <memory>
#include <functional>

class X
{
    public:
        // Non standard operators.
        // Because std::mem_fun_ref has a known weakness in that it can
        // not be used with methods that take parameters be reference.
        //
        // The principle is the same though. That the operator+ can be
        // used anywhere that the add() method can be used.

        X& operator+(X* rhs)  { return *this;}
        X& add(X* rhs)        { return *this;}
};

typedef X& (X::*MEMF)(X* rhs);

int main()
{
    MEMF    p1  = &X::add;
    MEMF    p2  = &X::operator+;

    X               value;
    std::vector<X>  data;

    std::for_each(data.begin(),
                  data.end(),
                  std::bind2nd(std::mem_fun_ref(&X::operator+),&value));
}

3

运算符和函数没有实质性的区别,只是运算符的语法不同。但原始运算符并非函数。


2
“操作符”是什么?
操作符”通常是对一个变量进行某种形式的标点符号运算。例如,两个整数之间默认的operator+行为是将它们相加。
“函数”是什么?
函数”是子程序——可重复使用的代码块。
它们之间有什么区别?
就用户代码而言,除了语法外,没有任何区别。请注意,如果您重载operator||operator&&或(在较小程度上)operator,,则会更改内置操作符语义。在&&||的情况下,您使通常短路的操作变成不短路的操作。在逗号的情况下,您需要确保从左到右评估参数,因为逗号运算符通常以这种方式运行。
“用户定义的operator+()”是函数还是运算符?
它都不是。它是用户定义的运算符重载。函数名不能以关键字“operator”开头,而运算符只是用于调用运算符重载的实际标点符号,即“+”或“-”。编辑:请注意,尽管从技术上讲它不是一个函数,但它具有函数调用的语义,正如@Martin York's excellent answer中所示。
运算符能在编译时操作操作数吗?它们总是在编译时操作吗?(就像C++中的sizeof())
不,sizeof无法重载。如果您想进行某种形式的编译时操作,则需要使用类似于模板元编程的东西。请注意,如果编译器能够在编译时执行计算,它可能会省略对您重载的运算符的调用。

我不同意你对“用户定义的operator+()是函数还是运算符?”的定义。用户类的重载运算符是一个函数/方法。使用运算符只是语法糖,实际上是一个函数/方法调用。a+b实际上是:a.operator+(b)。方法operator+的行为与类中的任何其他方法一样,甚至可以像任何其他方法(如add())一样取其地址。 - Martin York
@Martin York:它确实具有函数调用的语义,但这并不意味着它是一个函数。例如,您无法使用std::mem_fun_ref调用运算符重载。 - Billy ONeal
可能你可以。问题不在于重载运算符,而是因为mem_fun_ref无法处理具有引用参数的方法(这是mem_fun_ref存在的已知问题)。您可以像任何其他方法一样获取X :: operator+()的地址,并将其用作另一个方法一样使用。 - Martin York
@Martin:我不知道你可以这样调用它。 - Billy ONeal

0

0

函数和运算符之间没有太大的区别。您可以将使用运算符(例如'a+b')视为对函数operator+(a,b)的快捷方式,该函数针对a和b的类型进行定义。当然,原始类型(如整数)上的运算符和其他一些例外情况并不一定是这样定义的。

因此,回答您的一些具体问题:

用户定义的operator+()是函数还是运算符?

它是实现运算符的函数。

运算符能在编译时操作操作数吗?它们总是在编译时操作吗?

由于它是一个函数,因此它在运行时操作,但在某些情况下,编译器优化可以为某些运算符在编译时执行工作。我不确定您为什么要问这个问题,所以也许有些我不知道的东西。


0

函数和运算符之间只有两个小差别。

  1. 运算符可以以两种方式使用(x+yoperator+(a,b))。
  2. 运算符必须与内置的参数数量相同(operator==必须恰好有两个参数)。唯一的例外是函数调用operator(),它可以重载任意数量的任意参数。

-2

以下是运算符和函数之间的一些区别:

  1. 运算符不会将其参数推入堆栈,而函数会将其参数推入堆栈。

  2. 编译器了解运算符的操作,但不知道函数的输出。换句话说,运算符的操作在编译时定义,而函数的操作在运行时定义。


总的来说,你所说的两点在C ++中都是错误的 - 运算符重载才会发挥作用。 - Mat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接