实施出错"Rule of Three"
Implementation of "Rule of Three" gone wrong
以下是"三个规则"的错误实现,我试图理解。
调试程序,我发现调试器在清理int *k
方面存在问题,可以通过定义int *k = nullptr
或简单地将其设置为复制构造函数中合理的东西来解决。
但是,我不明白该程序的结果错误是如何存在的。
我知道,在复制分配构造函数v1
的int *k
之后,不再指向有效的内存地址。
class Vector2 {
public:
std::string name = "default";
int* k;
Vector2(int s, std::string n) : k(new int[s]), name(n) {
}
Vector2(const Vector2 &other) {
std::cout<< "Copy constructor: " << name << std::endl;
}
~Vector2() {
std::cout << "Deleting: " << name << std::endl;
delete[] k;
}
void swap(Vector2& other) {
using std::swap;
swap(k, other.k);
}
Vector2& operator=(Vector2 other) {
std::cout << "Copy assignment constructor: " << name << std::endl;
swap(other);
return *this;
}
};
int main() {
Vector2 v1 = Vector2(2, "v1");
Vector2 v2 = Vector2(4, "v2");
v1 = v2;
std::cout << &v1 << " " << &v2 << std::endl;
std::cout << &v1.k << " " << &v2.k << std::endl;
return 0;
}
以下是上述程序的控制台输出:
Copy constructor: default
Copy assignment constructor: v1
Deleting: default
0000001B5611FA28 0000001B5611FA78
0000001B5611FA50 0000001B5611FAA0
Deleting: v2
Deleting: v1
16:18:42: The program has unexpectedly finished.
它实际上非常简单:您的复制构造函数不会制作副本。实际上,它不会初始化任何成员,因此该构造函数创建的任何实例都充满了废话。
对于operator=(Vector2 other)
的调用,调用复制构造器来创建other
(这是三个规则的点),因此other
充满了废话。然后,您将this
(又名v1
)的有效k
与other
的k
交换。
然后,当调用v1
的驱动器时,它在糟糕的k
上调用delete[] k
->访问违规。
解决方案
使您的复制构造函数制作复制。或至少使其适当初始化k
(例如nullptr
)。
在 operator=
中构造 other
使用复制构造函数,该复制构造函数不会创建尖头的新副本。您的复制构造函数甚至可能不会复制k
,因为它是POD类型,因此不一定默认构造或默认复制。
然后,当它被破坏时,它试图将其销毁两次。或取决于诸如堆栈布局之类的随机因素,它可能根本不复制k
,然后尝试使用delete
无效的指针。
您的问题在Vector2(const Vector2 &other)
您通过按值模糊地隐式地使用operator =
中的构造函数;但是您无法将k分配给该构造函数中的任何值。
这会导致交换用无效的k替换有效的k,然后删除无效的k;导致您的崩溃。
可以通过列出事件的确切序列来得出解决方案,例如:更多的打印效果和测试,哪些参数在:
>从:v1 = v2;
-
v2
调用复制构造函数带有参数其他(其他是),特别是:其int* k
并不指向有效的内存。为简单起见,让我们称之为新的vector2 v3。 - 复制分配构造函数现在使用V3调用。
- 然后我们开始交换。
复制构造函数实际上发生了错误,因为v3
在步骤1中未正确初始化。
步骤2和步骤3基本上是"隐藏",将误差从v3
传输到v1
。
现在有趣的问题是,v3
如何实际生成?不是默认构造函数!
- Usages of std::move
- 使用 [] 运算符时"binding reference of type discards qualifiers"
- 如何处理 c++ 中类实现中的"invalid use of non-static data member"?
- 具有变量Number of Arguments的std::函数的矢量
- Capacity of a deque
- Deprecation of _writeBarrier()
- constexpr begin of a std::array
- 如何调整 std::vector of Eigen::MatrixXd 的大小
- C++ "error: invalid use of void expression"
- 我看到"use of undeclared identifier"错误,有人可以告诉我如何解决它吗?
- 赛通"Cannot take address of memoryview slice"
- C++ Version Of Double.longBitsToDouble
- 收到错误"invalid use of non-static data member 'stu::n' "
- C++ Usage of AsyncCallback
- 错误:"Left of getValue must have class/struct/union"
- Centos7 g++ "to_string is not in a member of std"
- 在C++中使用 Catch 测试框架编译错误"error: expected ';' at end of declaration list"
- 传递 std::vector of std::shared_ptr,而不是更新对象
- 实施出错"Rule of Three"
- 当我有多态指针时使用"rule of zero"