先看代碼(不想看代碼可以直接看代碼后的問題描述)
//header.h
#ifndef _HEADER_H
#define _HEADER_H
#define defaultSize 128
#include<iostream>
#include<string.h>
using namespace std;
class myString
{
private:
char *ch;
int curLength;
int maxSize;
public:
myString(int sz=defaultSize);
myString(const char *init);
myString(const myString& ob);
~myString(){delete []ch;}
void print();
int Length()const;
myString operator()(int pos, int len);
myString& operator = (myString& ob);
};
myString& myString::operator = (myString& ob)
{
if(&ob!=this)
{
delete[]ch;
this->ch = new char[ob.maxSize];
this->maxSize = ob.curLength;
strcpy(this->ch, ob.ch);
this->curLength = ob.curLength;
}
else
{
cerr<<"String copy error\n";
}
return *this;
}
myString myString::operator()(int pos, int len)
{
myString temp;
if(pos<0 || len<=0 || pos+len-1>=this->maxSize)
{
temp.curLength = 0;
temp.ch[0] = '\0';
}
else
{
if(pos+len-1 >= this->curLength)
len = this->curLength-pos;
temp.curLength = len;
for(int i=0,j=pos; i<len; ++i,++j)
temp.ch[i] = this->ch[j];
temp.ch[len] = '\0';
}
return temp;
}
int myString::Length()const
{
return this->curLength;
}
void myString::print()
{
cout<<this->ch<<endl;
}
myString::myString(int sz)
{
this->maxSize = sz;
this->ch = new char[this->maxSize+1];
if(this->ch == NULL)
{
cerr<<"Allocation ERROR\n";
exit(1);
}
this->curLength = 0;
ch[0] = '\0';
}
myString::myString(const char *init)
{
int len = strlen(init);
this->maxSize = (len > defaultSize) ? len : defaultSize;
this->ch = new char[this->maxSize+1];
if(this->ch == NULL)
{
cerr<<"Application Memory ERROR\n";
exit(1);
}
this->curLength = len;
strcpy(this->ch, init);
}
myString::myString(const myString& ob)
{
this->maxSize = ob.maxSize;
this->ch = new char[this->maxSize+1];
if(this->ch == NULL)
{
cerr<<"Application Memory ERROR\n";
exit(1);
}
this->curLength = ob.curLength;
strcpy(this->ch, ob.ch);
}
#endif
//main.cpp
#include"header.h"
int main()
{
myString st(10), st1("ABCDEFG");
myString st2(st1);
st.print(), st1.print(), st2.print();
st = st1(0, 4);//???
st.print();
return 0;
}
這是一個字符串類,問題出現在了兩個符號重載,()和=
()重載是想對字符串對象做一個切片,返回一個臨時對象,=重載就不用說了,就是賦值。
問題就出現在總是無法將這個切片后的臨時對象賦值給等號前的對象,編譯后如下:
在網上一番查找后找到一個類似問題
https://blog.csdn.net/u011068702/article/details/64443949
也就是說,在st1(0,4)時存在了一個臨時變量,當把這個臨時變量傳給st時,由於在=重載函數聲明中,參數為myString&,而並不是常量引用。
這個錯誤是C++編譯器的一個關於語義的限制。
如果一個參數是以非const引用傳入,c++編譯器就有理由認為程序員會在函數中修改這個值,並且這個被修改的引用在函數返回后要發揮作用。但如果你把一個臨時變量當作非const引用參數傳進來,由於臨時變量的特殊性,程序員並不能操作臨時變量,而且臨時變量隨時可能被釋放掉,所以,一般說來,修改一個臨時變量是毫無意義的,據此,c++編譯器加入了臨時變量不能作為非const引用的這個語義限制。
了解這個語義以后就簡單了,只需給=重載參數加上const常量限制符。
(類中=重載函數聲明也別忘了要加上const)
加上以后程序的運行結果
可以,很正確。
總結:
c++中臨時變量不能作為非const的引用參數
2019/12/14更新
最近看到一個類似問題,即C++11
int i=0; ++++i;//這樣是可以的 i++++;//這樣就是錯誤的
我們知道前++就是直接對對象自增后返回對象,而后++會先返回記錄當前值,在自增,最后返回一個無名的臨時對象,那么 i++++就是讓第一個后++返回的無名臨時對象再自增,這樣對C++是無意義的,所以這樣就無法編譯通過。//ps.這就是常說的 舉一隅以三隅反 吧