从重载运算符返回引用,并使用临时对象返回表达式
Returning reference from overloaded operatora and expression with temporary objects
我正在玩C++来提醒自己。所以我尝试了运算符 + 重载返回引用。这样做的动机是避免不必要的对象复制。看例子。我创建了类字符串和带有 + 的串联字符串。这只是实验性的,所以你会注意到一些丑陋的东西作为公共属性。
以下是代码的相关部分。
字符串.hpp
#ifndef STRING_HPP_
#define STRING_HPP_
#include <iostream>
using namespace std;
#ifndef CPP11
typedef wchar_t unicode16;
#else
typedef char16_t unicode16;
#endif //CPP11
class String {
unicode16 * value;
unsigned strLength;
void initEmpty() {
value = 0L;
strLength = 0;
}
static unsigned counter;
public:
static String ** trash;
unsigned id;
String::String() : value(0L), strLength(0){
id=counter++;
trash[id]=this;
cout << "Creating empty: " << id << "n";
}
String::String(const String &str);
String(const char *);
String(const unicode16 *);
unsigned length() const {
return strLength;
}
~String() {
wcout << L"Deleting " << id << ": " << value << L"n";
trash[id]=0L;
delete value;
}
String & operator +(String &);
unicode16 * getValue() {
return value;
}
};
#endif /* STRING_HPP_ */
字符串.cpp
#include "String.hpp"
#include "../exception/IllegalArgumentException.h"
#include <string.h>
unsigned String::counter = 0;
String ** String::trash = new String *[100]();
String::String(const String & str) {
value = new unicode16[str.strLength + 1];
strLength = str.strLength;
for(int i = 0; i < strLength ; i++) {
value[i] = str.value[i];
}
value[strLength] = 0;
id = counter++;trash[id]=this;
wcout << L"Created (copy): " << id << ": " << value << L"n";
}
String::String(const char *charArray) {
if (charArray == 0L) {
throw IllegalArgumentException("Char array pointer is null");
}
strLength = strlen(charArray);
value = new unicode16[strLength + 1];
for (int i = 0; i < strLength; i++) {
value[i] = (unicode16)charArray[i];
}
value[strLength] = 0;
id = counter++;trash[id]=this;
wcout << L"Created (char *): " << id << ": " << value << L"n";
}
String::String(const unicode16 *utfArray) {
if (utfArray == 0L) {
throw IllegalArgumentException("Unicode array pointer is null");
}
strLength = wcslen(utfArray);
value = new unicode16[strLength + 1];
for (int i = 0; i < strLength; i++) {
value[i] = utfArray[i];
}
value[strLength] = 0;
id = counter++;
trash[id]=this;
wcout << L"Created (unicode): " << id << ": " << value << L"n";
}
String & String::operator +(String &str) {
unsigned newLength = length() + str.length();
unicode16 * newArray = new unicode16[newLength + 1];
wcscpy(newArray, value);
wcscpy(newArray + strLength, str.value);
String * strPointer = new String();
strPointer->value = newArray;
strPointer->strLength = newLength;
String &result = *strPointer;
wcout << L"Empty loaded: " << result.id << ": " << result.value << L"n";
return result;
}
和主要方法
#include "../string/string.hpp"
#include <iostream>
using namespace std;
int metodica(void) {
String & please = String("Please");
String meString = "me";
String & me = meString;
String & delStrRef = String(" delete ");
String & result1 = please + delStrRef + me;
wcout << result1.getValue() << L"n";
delete &result1;
return 0;
}
int main(void) {
metodica();
cout << "These are not deletedn";
for (int i = 0; i < 100; i++) {
if (String::trash[i] != 0L) {
wcout << String::trash[i]->getValue() << "n";
}
}
}
使用 VS2010 编译器和链接器在 CDT 中执行此操作,我得到了以下输出
创建(字符*):0:请
创建(字符*):1:我
已创建(字符*):2:删除
创建空:3
空载: 3:请删除
创建空:4
空加载:4:请删除我
请删除我
删除4:请删除我
删除2:删除
删除 1:我
删除 0:请
这些不会被删除
请删除
问题是为什么在表达式中创建的临时对象 请 + delStrRef + me; 不被删除。它不应该在表达式的末尾被删除,或者如果引用是临时对象而不是对象本身,它就会有所不同。
String & String::operator +(String &str) {
...
String * strPointer = new String();
...
String &result = *strPointer;
...
return result;
}
您手动创建了该对象,然后返回对该对象的引用。因此,编译器没有插入delete
运算符。因此,如果没有内存泄漏和手动删除对象,则无法返回引用。
例如Qt
库中operator+
实现为
Q_EXPORT inline const QString operator+( const QString &s1, const QString &s2 ) {
QString tmp( s1 );
tmp += s2;
return tmp;
}
申报operator+=
QString &operator+=( const QString &str );
相关文章:
- 返回对临时对象的引用
- 为什么在按值返回时创建临时对象,而不是在按值传递给函数参数时创建临时对象
- 为什么在此示例中可以返回临时对象
- 检查成员函数是否返回临时对象或数组对象
- 在没有返回值优化的情况下将两个对象加在一起时,将创建多少个临时对象
- 从函数返回引用是否会导致在使用'auto'时创建新的临时对象?
- 返回对本地临时对象 C++ 的引用
- 临时对象的子对象是否保证在返回时移动
- 模板类型推导警告返回对本地临时对象的引用
- 复制构造函数返回临时对象
- C++返回临时对象混乱
- const引用是否延长临时对象返回的临时对象的寿命
- C++:通过引用将 std::vector<> 成员返回到临时对象
- 当我从内联函数返回字符串时,会创建多少个临时对象
- 正在返回临时对象并绑定到常量引用
- 返回临时对象并使用其引用
- 使用默认构造函数返回临时对象时,Destuctor调用了两次
- 返回临时对象是否会在C++中创建临时对象
- c++复制构造函数和返回临时对象的冲突
- 为什么在返回临时对象之前调用move构造函数?