-2

赋值运算符 ( =) 是否必须始终将右值复制到左值中,还是完全取决于它所操作的操作数的类型?抱歉,如果这很愚蠢,但无论我读到什么,都写着它只是将右侧的值复制到左侧。我想弄清我的事实。

请举一个C++的例子。

4

5 回答 5

2

它实际上完全取决于您如何实现赋值运算符和类的组成......在 C++ 中,POD 类或结构的默认编译器创建的赋值运算符方法将简单地逐位复制 RHS对象到 LHS 对象中,但是用户定义的赋值运算符可以做任何你想做的事情。它总是属于 LHS 对象,但它不需要做任何复制,或者如果你愿意,它可能会产生任何数量的副作用。

于 2012-06-19T21:04:07.607 回答
2

您可以随意重载赋值运算符,但 C++ 中的通常实现是这样的:

class MyObject
{
public:
    MyObject& operator=(const MyObject& rhs)
    {
        if (this != &rhs)
            x = rhs.x;
        return *this;
    }

private:
    int x;
};

这样做的原因是允许自定义对象的简单分配。由于用户定义的类和结构可能很复杂,因此有时您需要提供自定义赋值运算符来执行诸如指针成员的深拷贝之类的操作。

MyObject a;
MyObject b;
b = a; // calls assignment operator b.operator=(a);

请注意,您不能重载 C 中的运算符,而 Java 可能会有所不同。

编辑:

正如 Griwes 指出的那样,您可能想知道的其他事情是,如果您不指定一个,编译器将为您的用户定义对象生成一个隐式赋值运算符。有时您想定义或声明它只是为了避免编译器生成的默认行为。

还有一些=令牌的用法实际上会调用复制构造函数,例如,如果您像这样修改我以前的用例:

MyObject a;
MyObject b = a; // this calls the copy constructor (also implicitly defined if not provided)

它可能看起来像一个赋值,但在上述情况下不会调用自定义提供的运算符。有关何时定义或不想定义赋值运算符的更多原因,请查看 Wikipedia 上的三规则。

于 2012-06-19T21:06:11.897 回答
2

赋值运算符 (=) 是否必须始终将右值复制到左值中。

不。对于用户定义的类型,它不会做这样的事情。相反,它调用适当的operator=函数。考虑这些类:

#include <iostream>
struct Half {
  int i;
  void operator=(int j) { i = j/2; }
};
struct Double {
  int i;
  void operator=(int j) { i = j*2; }
};
int main () {
  Half h;
  h = 3;
  Double d;
  d = 3;
  std::cout << h.i << " " << d.i << "\n";
  // Result is "1 6"
}

如您所见,赋值运算符可以自由执行它认为合适的任何操作。在这种情况下,它显然不仅仅是一个“副本”。

于 2012-06-19T21:12:43.947 回答
0

不同的语言使用不同的概念

Java 和 C++ 和 C+ 是的,这是一个赋值,除非被另一个函数重载

T-SQL = 成为测试和作业

于 2012-06-19T21:04:00.447 回答
0

复制这个词太笼统了。

在 C 中,如果您分配给指针,则不会复制实际值,但它将保存存储右侧操作数的内存地址。

int *ptr = (int *)malloc(sizeof(int *));
*ptr = 1; // points at whatever address 1 has
ptr = 1; // points at address 1, containing ????
于 2012-06-19T21:04:50.930 回答