CPP-operator= overloding

本文介绍了C++中运算符重载的概念与实现方法,特别是赋值运算符(=)的重载技巧。讨论了如何使用常引用作为右操作数,并返回左操作数的引用以支持链式操作。此外,还强调了自赋值检查的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

c++很好的一个优点就是根据用户定义的类,操作符有不同的意义。这就叫operator overloading. 一般通过在类中提供一个特别的成员函数来实现。可以被overloading的操作符有以下几种:

= (assignment operator)
+ - * (binary arithmetic operators)
+= -= *= (compound assignment operators)
== != (comparison operators)

对assignment operator(=), 一些最基本的guidelines很重要。

一个典型的=overloading实现如下:

class Myclass{
public:
    Myclass & operator= (const Myclass &opb);
    ..
    }
Myclass a,b;
b = a; //same as a.operator(a);

注意=操作符中,右边的操作数是个常引用(const-reference)。原因是我们不希望改变右边的值,我们只想将右边的值给左边。
另外,返回值是个引用,这主要是为了实现链式操作(operator chaining):

int a,b,c,d,e;
a = b = c = d = e = 520;

编译器解释为:

a=(b=(c=(d=(e=520))));

即e=520首先执行,然后返回e作为结果。e的值再给d….。为了实现这个,赋予值操作必须返回一个值。应该返回的值是操作符左边的一个引用。

另外,我们并没有指定返回值是一个常引用。因为这样允许写以下代码:

(a = b) = c;

粗一看,你可能觉得应该设定返回一个常引用来避免这种情况。但statements like this will work with primitive types。更糟糕是是有些编译工具依赖此行为。因此返回一个非常引用是非常重要的事情。

// Take a const-reference to the right-hand side of the assignment.
  // Return a non-const reference to the left-hand side.
  MyClass& MyClass::operator= (const MyClass &rhs) {
    ...  // Do the assignment operation!

    return *this;  // Return a reference to myself.
  }

注意this 是一个指针,他指向成员函数正在被调用的对象。由于a=b被处理为
a.operator(b). 对象a 的成员函数被调用。
但是,这个成员函数要返回一个指向对象的引用。而不是一个指向对象的指针。因此返回*this, 它返回的是this指向的东西,而不是指针本身。

最后一件重要事情是检查自赋值操作。当自定义类有分配内存操作时,这一点非常重要。看以下例子:

MyClass& MyClass::operator=(const MyClass &rhs) {
    // 1.  Deallocate any memory that MyClass is using internally
    // 2.  Allocate some memory to hold the contents of rhs
    // 3.  Copy the values from rhs into this instance
    // 4.  Return *this
  }

以下调用:

MyClass mc;
mc = mc; 

因为mc同时在左手边和右手边,第一件事情发生的是mc将释放它保持的任何内存。但是,这个内存也是拷贝操作需要用的内存,因为mc也在右手边。因此操作完全混乱。

最容易的是进行自调用检查,对此问题有很多解。在此采用比较地址方法,如果两个地址相同,则认为是同样的,不进行赋值操作。如果不同,继续。

因此,正确和安全的版本是:

 MyClass& MyClass::operator=(const MyClass &rhs) {

    // Only do assignment if RHS is a different object from this.
    if (this != &rhs) {
      ... // Deallocate, allocate new space, copy values...
    }

    return *this;
  }

**总结:
1) 右手边是常引用;
2) 返回是左边非常引用;
3) 比较指针避免自赋值。**

C:\Users\Administrator\Documents\贪吃蛇.cpp In function 'void initGame(Snake&, Food&)': 33 40 C:\Users\Administrator\Documents\贪吃蛇.cpp [Warning] extended initializer lists only available with -std=c++11 or -std=gnu++11 [enabled by default] 33 16 C:\Users\Administrator\Documents\贪吃蛇.cpp [Warning] extended initializer lists only available with -std=c++11 or -std=gnu++11 [enabled by default] 33 16 C:\Users\Administrator\Documents\贪吃蛇.cpp [Warning] extended initializer lists only available with -std=c++11 or -std=gnu++11 [enabled by default] 33 16 C:\Users\Administrator\Documents\贪吃蛇.cpp [Warning] extended initializer lists only available with -std=c++11 or -std=gnu++11 [enabled by default] 33 16 C:\Users\Administrator\Documents\贪吃蛇.cpp [Warning] extended initializer lists only available with -std=c++11 or -std=gnu++11 [enabled by default] 33 16 C:\Users\Administrator\Documents\贪吃蛇.cpp [Warning] extended initializer lists only available with -std=c++11 or -std=gnu++11 [enabled by default] 33 16 C:\Users\Administrator\Documents\贪吃蛇.cpp [Error] no match for 'operator=' (operand types are 'std::vector<_COORD>' and '<brace-enclosed initializer list>') 33 16 C:\Users\Administrator\Documents\贪吃蛇.cpp [Note] candidate is: 69 0 d:\program files (x86)\dev-cpp\mingw64\lib\gcc\x86_64-w64-mingw32\4.8.1\include\c++\vector In file included from d:\program files (x86)\dev-cpp\mingw64\lib\gcc\x86_64-w64-mingw32\4.8.1\include\c++\vector 5 C:\Users\Administrator\Documents\贪吃蛇.cpp from C:\Users\Administrator\Documents\贪吃蛇.cpp 160 5 d:\program files (x86)\dev-cpp\mingw64\lib\gcc\x86_64-w64-mingw32\4.8.1\include\c++\bits\vector.tcc [Note] std::vector<_Tp, _Alloc>& std::vector<_Tp, _Alloc>::operator=(const std::vector<_Tp, _Alloc>&) [with _Tp = _COORD; _Alloc = std::allocator<_COORD>] 160 5 d:\program files (x86)\dev-cpp\mingw64\lib\gcc\x86_64-w64-mingw32\4.8.1\include\c++\bits\vector.tcc [Note] no known conversion for argument 1 from '<brace-enclosed initializer list>' to 'con
最新发布
03-28
<think>好的,用户遇到了C++编译器警告和错误,特别是关于extended initializer lists和operator=的问题。我需要先理解这些错误的具体原因,然后给出解决方案。 首先,用户提到编译器提示“extended initializer lists only available with -std=c++11”。这表明用户使用了C++11中的初始化列表特性,但编译器没有启用C++11模式。在C++98中,初始化聚合类型(如数组、结构体)时,不能使用大括号{}的列表初始化,而C++11扩展了这一功能。因此,用户需要确保编译器使用C++11或更高标准进行编译。解决方法是添加编译选项-std=c++11或-std=gnu++11[^1][^2]。 接下来是“error: operator= brace-enclosed initializer list”。这可能是因为用户尝试用大括号初始化列表给不支持列表初始化的对象赋值。例如,在C++98中,vector的operator=不接受初始化列表,需要使用构造函数或push_back方法。用户需要检查代码中是否有类似vector<int> v; v = {1,2,3};的语句,并修改为C++98兼容的方式,比如先声明并初始化,或者逐个添加元素[^2]。 另外,用户提到vector相关的问题。在C++98中,vector的初始化也需要使用构造函数,而不能直接使用初始化列表。例如,应该用vector<int> v(3, 0);来初始化为三个0,而不是用{}。同时,范围for循环在C++98中也不支持,需要使用传统的循环结构。 需要提醒用户检查代码中是否还有其他C++11的特性,比如auto关键字、lambda表达式等,这些在C++98中都是无效的。建议用户升级到C++11或更高标准以获得更好的支持,或者修改代码以符合C++98的规范。 最后,可能需要用户提供具体的代码示例,以便更准确地定位问题,但根据现有信息,上述解决方案应该能覆盖大部分情况。</think>针对C++编译器报错`extended initializer lists`和`operator=`相关错误,以下是逐步解决方案: --- ### 1. 理解错误原因 - **错误1**:`warning: extended initializer lists only available with -std=c++11` - **原因**:使用了C++11的初始化列表语法(如`{}`初始化对象),但编译器默认使用C++98标准 - **错误2**:`error: no match for 'operator=' with a brace-enclosed initializer list` - **原因**:在C++98中,STL容器(如`vector`/`map`)无法直接通过`{}`赋值或初始化[^2] --- ### 2. 解决方案 #### 方法一:启用C++11标准(推荐) 在编译命令中添加`-std=c++11`或`-std=gnu++11`标志: ```bash g++ -std=c++11 your_code.cpp -o output ``` #### 方法二:修改代码适配C++98 **场景1:初始化`vector`** ```cpp // C++11允许的写法(需加编译选项) std::vector<int> v = {1,2,3}; // C++98兼容写法 int temp[] = {1,2,3}; std::vector<int> v(temp, temp + sizeof(temp)/sizeof(int)); ``` **场景2:初始化`map`** ```cpp // C++11允许的写法(需加编译选项) std::map<std::string, int> m = {{"apple",1}, {"banana",2}}; // C++98兼容写法 std::map<std::string, int> m; m.insert(std::make_pair("apple", 1)); m.insert(std::make_pair("banana", 2)); ``` **场景3:`operator=`赋值** ```cpp // C++11允许的写法(需加编译选项) std::vector<int> v; v = {4,5,6}; // C++98兼容写法 int temp[] = {4,5,6}; v.assign(temp, temp + sizeof(temp)/sizeof(int)); ``` --- ### 3. 关键原理 1. C++98未定义`std::initializer_list`类型,因此无法处理大括号初始化列表[^1] 2. STL容器的赋值运算符在C++98中不接受初始化列表参数 3. C++11引入的统一初始化语法需要显式启用标准 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值