[英]Why we have to use const in copy constructor and assignment operator in visual studio 2019 and onwards versions
As you can see that operator+ is returning an object of class type MyString.如您所见,operator+ 返回 class 类型 MyString 的 object。
The assignment operator is not accepting this object in Visual Studio 2019 and giving an error of E0349 that no operands matches.赋值运算符在 Visual Studio 2019 中不接受此 object 并给出 E0349 错误,没有操作数匹配。 But, in Visual Studio 2012, it is running fine.但是,在 Visual Studio 2012 中,它运行良好。
Code:代码:
#include <iostream>
using namespace std;
class MyString {
private:
char* str;
int length;
public:
MyString();
MyString(const MyString&);
bool operator!();
friend ostream& operator<<(ostream&, MyString&);
friend istream& operator>>(istream&, MyString&);
MyString& operator=(const MyString&);
MyString operator+(MyString&);
MyString& operator-(MyString);
MyString& operator ++ ();
MyString& operator -- ();
bool operator<(MyString&);
char& operator[](int);
char* operator()(int, int);
void my_strcpy(char*&, char*);
int my_strlen(char*);
};
MyString::MyString() {
str = new char[1];
str[0] = '\0';
length = 0;
}
MyString::MyString(const MyString& obj) {
int size = my_strlen(obj.str) + 1;
str = new char[size];
cout << "copy constructor called\n";
my_strcpy(str, obj.str);
}
bool MyString::operator!() {
if (str[0] == '\0')
return true;
return false;
}
ostream& operator<<(ostream& output, MyString& obj) {
output << obj.str;
return output;
}
istream& operator>>(istream& input, MyString& obj) {
delete obj.str;
obj.str = new char[50];
input.getline(obj.str, 50);
return input;
}
MyString& MyString::operator=(const MyString& obj) {
if (this != &obj) {
my_strcpy(str, obj.str);
}
return *this;
}
char& MyString::operator[](int index) {
if (index >= 0 && index < my_strlen(str))
return str[index];
else {
clog << "Index is out of range\n", exit(1);
}
}
void MyString::my_strcpy(char*& destination, char* source) {
int len_des = my_strlen(destination);
int len_source = my_strlen(source);
delete[]destination;
destination = new char[len_source + 1];
int index = 0;
while (source[index] != '\0')
destination[index] = source[index++];
destination[index] = '\0';
}
MyString MyString::operator+(MyString& obj) {
MyString newObj;
int size = my_strlen(str) + my_strlen(obj.str) + 1;
newObj.str = new char[size];
char* temp = newObj.str;
int index_str = 0;
while (str[index_str] != '\0')
*newObj.str++ = str[index_str++];
index_str = 0;
while (obj.str[index_str] != '\0')
*newObj.str++ = obj.str[index_str++];
*newObj.str = '\0';
newObj.str = temp;
cout << newObj.str << endl;
return newObj;
}
MyString& MyString::operator ++ () {
int size = my_strlen(str) + 2;
char* new_str = new char[size];
char* temp = new_str;
int index = 0;
while (str[index] != '\0')
*new_str++ = str[index++];
*new_str++ = 'a';
*new_str = '\0';
delete[]str;
str = temp;
return *this;
}
MyString& MyString::operator -- () {
int size = my_strlen(str);
char* new_str = new char[size];
char* temp = new_str;
int index = 0;
while (index < size - 1)
*new_str++ = str[index++];
*new_str = '\0';
delete[]str;
str = temp;
return *this;
}
MyString& MyString::operator-(MyString obj) {
bool find = true;
int obj_str_len = my_strlen(obj.str);
int str_len = my_strlen(str);
int start_ind = 0, end_ind = 0;
if (str_len > obj_str_len) {
for (int i = 0; str[i] != '\0'; i++) {
if (str[i] == obj.str[0]) {
start_ind = i;
find = true;
for (int j = i + 1, k = 1; obj.str[k] != '\0' && find; j++, k++) {
if (str[j] != obj.str[k]) {
find = false;
}
end_ind = j + 1;
}
if (find)
break;
}
}
if (find) {
while (str[end_ind] != '\0') {
str[start_ind++] = str[end_ind++];
}
str[str_len - (end_ind - start_ind)] = '\0';
}
}
return *this;
}
bool MyString::operator<(MyString& obj) {
if (my_strlen(str) < my_strlen(obj.str))
return true;
else if (my_strlen(str) > my_strlen(obj.str))
return false;
for (int i = 0; str[i] != '\0'; i++) {
if (str[i] < obj.str[i])
return true;
else if (str[i] > obj.str[i]) {
return false;
}
}
return false;
}
char* MyString::operator()(int starting_index, int ending_index) {
int new_str_size = ending_index - starting_index + 2;
char* new_str = new char[new_str_size];
char* temp = new_str;
int index = 0;
int str_len = my_strlen(str);
while (starting_index < str_len && index < 10)
*new_str++ = str[starting_index++], index++;
*new_str = '\0';
return temp;
}
int MyString::my_strlen(char* str) {
int size = 0;
while (str[size] != '\0')
size++;
return size;
}
int main() {
MyString str1, str2, str3, str4, str6;
if (!str1)
{
cout << "String 1 is Empty.\n";
cout << "Str 1 = " << str1 << endl << endl << endl;
}
cout << "Enter String 1:\t";
cin >> str1;
cout << "Enter String 2:\t";
cin >> str2;
cout << "\n\n\nUser Entered:\n";
cout << "String 1 = " << str1 << endl;
cout << "String 2 = " << str2 << endl << endl << endl;
cout << "Before str1 = str1; str1 = " << str1 << endl;
str1 = str1;
cout << "After str1 = str1, str1 = " << str1 << endl << endl << endl;
cout << "Before str4 = str3 = str1+str2\n";
cout << "str1 = " << str1 << endl;
cout << "str2 = " << str2 << endl;
cout << "str3 = " << str3 << endl;
cout << "str4 = " << str4 << endl;
str4 = str3 = str1 + str2;
cout << "\n\n\nAfter str4 = str3 = str1+str2\n";
cout << "str1 = " << str1 << endl;
cout << "str2 = " << str2 << endl;
cout << "str3 = " << str3 << endl;
cout << "str4 = " << str4 << endl;
cout << "\n\n\nEnter String 3:\t";
cin >> str3;
cout << "\n\n\nEnter String 4:\t";
cin >> str4;
cout << "\n\n\nstr3 = " << str3 << endl;
cout << "str4 = " << str4 << endl;
if (str3 < str4)
cout << "String 3 is Less than String 4.\n";
else
cout << "String 3 is NOT Less than String 4.\n";
MyString str5 = str1 + str2;;
cout << "\n\n\nStr5:\t" << str5 << endl;
cout << "Str5[7]:\t" << str5[7] << endl;
str5[7] = '$';
cout << "\n\nStr5:\t" << str5 << endl;
cout << "\n\n\nstr5(5, 10):\t" << str5(5, 10) << endl;
cout << "\n\n ++Str3 :\t" << ++str3 << endl;
str5 = str4 - str3;
cout << "\n\n Str4 - Str3 :\t" << str5 << endl;
cout << "\n\n --Str3 :\t" << --str3 << endl;
cout << "\n\n --Str3 :\t" << --str3 << endl;
str5 = str4 - str3;
cout << "\n\n Str4 - str3 :\t" << str5 << endl;
return 0;
}
Problem:问题:
The lines str3 = str1 + str2;
行str3 = str1 + str2;
and MyString str4 = str1 + str2;
和MyString str4 = str1 + str2;
will give an error that no operands matches.将给出没有操作数匹配的错误。 This error starts from Visual Studio 2019 and onwards versions.此错误从 Visual Studio 2019 及更高版本开始。
But, when I use const
in both copy constructor and assignment operator (such as MyString(const MyString&);
MyString& operator=(const MyString&);
), both lines ( str3 = str1 + str2; MyString str4 = str1 + str2;
) looks fine to compiler.但是,当我在复制构造函数和赋值运算符(例如MyString(const MyString&);
MyString& operator=(const MyString&);
)中都使用const
时,两行( str3 = str1 + str2; MyString str4 = str1 + str2;
)看起来对编译器很好。
But if I Write str3 = str1;
但是如果我写str3 = str1;
and MyString str4 = str2;
和MyString str4 = str2;
now there is no need to write const
in the copy constructor and assignment operator.现在不需要在拷贝构造函数和赋值运算符中写const
了。
Why is the compiler showing this behaviour.?为什么编译器显示这种行为。?
The assignment operator that you have defined (ie, taking a non-const reference) requires that its argument be (or be convertible to ) an lvalue reference because it is non-const.您定义的赋值运算符(即采用非常量引用)要求其参数是(或可转换为)左值引用,因为它是非常量。
However, the right-hand side of the assignment operator in the expression, str3 = str1 + str2
is the result of the addition, which is a temporary value and, as such, is a prvalue that cannot be (implicitly) converted to an lvalue.但是,表达式中赋值运算符的右侧str3 = str1 + str2
是加法的结果,它是一个临时值,因此是不能(隐式)转换为左值的纯右值.
Adding the const
qualifier to the parameter allows that operator to accept rvalue references (because you are explicitly stating that the referred-to value will not be modified).向参数添加const
限定符允许该运算符接受右值引用(因为您明确声明不会修改引用的值)。
This is why, generally, copy constructors and copy assignment operators are defined with const &T
parameters (though they don't have to be).这就是为什么通常使用const &T
参数定义复制构造函数和复制赋值运算符(尽管它们不一定是)。
For a fuller discussion of the differences between lvalues and rvalues, see here: Exact difference between rvalue and lvalue .有关左值和右值之间差异的更全面讨论,请参见此处:右值和左值之间的确切区别。
On why/how this "binding of a temporary to an lvalue reference" was allowed in the earlier version(s) of Visual Studio, see: Non-const reference bound to temporary, Visual Studio bug?关于为什么/如何在 Visual Studio 的早期版本中允许这种“将临时值绑定到左值引用”,请参阅:非常量引用绑定到临时的 Visual Studio 错误? . .
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.