#include <iostream>
using namespace std;
class Box {
public:
double getVolume(void) {
return length * breadth * height;
}
void setLength( double len ) {
length = len;
}
void setBreadth( double bre ) {
breadth = bre;
}
void setHeight( double hei ) {
height = hei;
}
// Overload + operator to add two Box objects.
Box operator+(const Box& b) {
Box box; //local object?
box.length = this->length + b.length;
box.breadth = this->breadth + b.breadth;
box.height = this->height + b.height;
return box;
}
private:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
};
代码来源:https://www.tutorialspoint.com/cplusplus/cpp_overloading.htm。以上运营商如何运作?令我感到困惑的是,与Java相反,在C ++ Box框中创建了一个对象,但该方法返回的对象的生命周期仅限于方法范围(运算符)。
所以我尝试了另一个例子:
template <typename T>
class SmartPointer
{
T *ptr;
int numElem; //-1 if an element. >=0 if an array
public:
SmartPointer(T pNum);
SmartPointer();
SmartPointer(T *pArray, int pSize);
~SmartPointer();
SmartPointer(std::initializer_list<T> nums);
T getValue() const;
T getValue(int index) const;
void setValue(T pNum);
void setValue(T pNum, int index);
int getNumElem() const;
SmartPointer<T> operator+ (const SmartPointer<T>& ptr);
SmartPointer<T> operator- (const SmartPointer<T>& ptr);
SmartPointer<T> operator* (const SmartPointer<T>& ptr);
};
template <class T>
SmartPointer<T> SmartPointer<T>::operator+ (const SmartPointer<T>& p_ptr)
{
int pSize = this->getNumElem();
T tempArray[pSize] = {0};
for(int i = 0; i < this->getNumElem(); i++)
{
int result = this->getValue(i) + p_ptr.getValue(i);
tempArray[i] = result;
}
SmartPointer<T> result(tempArray, pSize); (line 60)
return result; (line 61)
}
}
我正在尝试实现smartpointer,我想重载+就像它是一个分量加法(如向量加法)。
然后,如果我运行以下代码:
SmartPointer<int> sPointer6({10,11,12});
SmartPointer<int> sPointer7({10,11,12});
SmartPointer<int> sPointer8 = sPointer6 + sPointer7;
cout << sPointer8.getValue(0) << endl; //getValue(index)
cout << sPointer8.getValue(1) << endl;
cout << sPointer8.getValue(2) << endl;
我得到以下输出:
1310912
1338712
24
但如果我用
替换第60行和第61行return SmartPointer<T>(tempArray, pSize);
然后我得到以下输出:
20
22
24
为什么我会得到不同的输出?为什么第一个例子工作但不是smartpointer示例?
答案 0 :(得分:1)
您的模板类Chriss-MacBook-Pro-2:build louisduplessis$ cmake .. && make
In file included from /Library/Developer/CommandLineTools/usr/include/c++/v1/utility:203:
/Library/Developer/CommandLineTools/usr/include/c++/v1/cstdint:158:8: error: no
member named 'uint8_t' in the global namespace
using::uint8_t;
~~^
/Library/Developer/CommandLineTools/usr/include/c++/v1/cstdint:159:8: error: no
member named 'uint16_t' in the global namespace
using::uint16_t;
~~^
/Library/Developer/CommandLineTools/usr/include/c++/v1/cstdint:160:8: error: no
member named 'uint32_t' in the global namespace
using::uint32_t;
~~^
/Library/Developer/CommandLineTools/usr/include/c++/v1/cstdint:161:8: error: no
member named 'uint64_t' in the global namespace
using::uint64_t;
~~^
/Library/Developer/CommandLineTools/usr/include/c++/v1/cstdint:178:8: error: no
member named 'uint_fast8_t' in the global namespace
using::uint_fast8_t;
~~^
/Library/Developer/CommandLineTools/usr/include/c++/v1/cstdint:179:8: error: no
member named 'uint_fast16_t' in the global namespace
using::uint_fast16_t;
~~^
/Library/Developer/CommandLineTools/usr/include/c++/v1/cstdint:180:8: error: no
member named 'uint_fast32_t' in the global namespace
using::uint_fast32_t;
~~^
fatal error: too many errors emitted, stopping now [-ferror-limit=]
20 errors generated.
make[2]: *** [CMakeFiles/path_planning.dir/src/main.cpp.o] Error 1
make[1]: *** [CMakeFiles/path_planning.dir/all] Error 2
make: *** [all] Error 2
未定义SmartPointer
和复制构造函数,因此定义了默认的operator=
或复制构造函数。返回的副本operator=
引用已释放的数组sPointer8
。它是UB,它是由于违反了自由规则。
如果您使用ptr
代替C-array std::vector<T>
及其大小ptr
,则不会遇到此类错误。
答案 1 :(得分:1)
我很困惑的是,与Java相反,在C ++ Box框中会在堆栈上创建一个对象,但该方法返回的对象的生命周期仅限于方法范围(运算符)。
Box operator+(const Box& b) {
Box box; //local object?
// ...
return box;
}
正确,但这不是问题,因为对象是复制。
Box
对象定义了一个隐式的默认“复制构造函数”(带有签名Box (Box const & b)
)和一个隐式operator=()
(带有签名Box & (Box const & b)
。从C ++ 11开始,也是一个“移动构造函数”(带签名Box (Box && b)
)和Box & operator=(Box const & b)
所以,当你写
Box a, b, c;
// ...
Box d { a + b };
c = a + b;
operator+()
创建在Box
中复制(或移动)的临时result
(d
),通过复制或移动构造函数,或c
在它被破坏之前,通过operator=()
。
对于Box
,默认的复制/移动构造函数和operator=()
是正常的,因为没有涉及内存分配或其他复杂操作(它们只是复制length
,{{1 },breadth
)。
问题出现在您的height
(如果我理解正确的话)动态分配的内存(SmartPointer
)。
默认构造函数(等等)已经不行了,因为它复制立即解除分配的ptr
(破坏临时对象)的值(如果已添加{{ 1}} ptr
。
结果就是当你写
时delete[]
~SmartPointer()
中的SmartPointer<int> sPointer8 = sPointer6 + sPointer7;
指向一个空闲的内存区域。并且程序可以用于其他目的(其他变量)。
ptr
这是因为(我想)在临时sPointer8
中为So, when you get
1310912
1338712
24
和result[0]
保留的内存是免费的,并且可以重用一个或多个其他变量。
你得到的结果不同
result[1]
和
sPointer6 + sPointer7
这是一个纯粹的死亡,因为在这两种情况下你都在访问免费内存,在这两种情况下都是UB(Undefined Bahaviour)。
UB的意思是:任何事情都可能发生。
解决方案:编写复制/移动构造函数,以及 SmartPointer<T> result(tempArray, pSize);
return result;
来管理 return SmartPointer<T>(tempArray, pSize);
中分配的内存的复制和复制。
或者,更好的是,避免直接管理内存并使用标准库中提供的容器/智能指针。
另一点:
operator=()
不是(标准C ++):您无法使用运行时值初始化C样式数组。