sta*_*low 11 c++ visual-studio
我有一个指向动态分配数组的类,所以我创建了复制构造函数和赋值运算符函数.由于复制构造函数和赋值运算符函数执行相同的工作,我从赋值运算符函数调用复制构造函数但得到"error C2082: redefinition of formal parameter".我正在使用Visual Studio 2012.
// default constructor
FeatureValue::FeatureValue()
{
m_value = NULL;
}
// copy constructor
FeatureValue::FeatureValue(const FeatureValue& other)
{
m_size = other.m_size;
delete[] m_value;
m_value = new uint8_t[m_size];
for (int i = 0; i < m_size; i++)
{
m_value[i] = other.m_value[i];
}
}
// assignment operator function
FeatureValue& FeatureValue::operator=(const FeatureValue& other)
{
FeatureValue(other); // error C2082: redefinition of formal parameter
return *this;
}
Run Code Online (Sandbox Code Playgroud)
Cap*_*ous 18
违规行不是你想象的那样.它实际上声明了一个other类型的变量FeatureValue.这是因为构造函数没有名称而且无法直接调用.
只要操作符未声明为虚拟,就可以安全地从构造函数中调用复制赋值运算符.
FeatureValue::FeatureValue(const FeatureValue& other)
: m_value(nullptr), m_size(0)
{
*this = other;
}
// assignment operator function
FeatureValue& FeatureValue::operator=(const FeatureValue& other)
{
if(this != &other)
{
// copy data first. Use std::unique_ptr if possible
// avoids destroying our data if an exception occurs
uint8_t* value = new uint8_t[other.m_size];
int size = other.m_size;
for (int i = 0; i < other.m_size; i++)
{
value[i] = other.m_value[i];
}
// Assign values
delete[] m_value;
m_value = value;
m_size = size;
}
return *this;
}
Run Code Online (Sandbox Code Playgroud)
这将只是花花公子或你可以使用Vaughn Cato的答案中建议的复制和交换习语的典型指南
Vau*_*ato 11
您不能像任何其他方法一样直接调用构造函数.你在做什么实际上是声明一个名为othertype 的变量FeatureValue.
看一下复制和交换习惯用法,以避免赋值运算符和复制构造函数之间的重复:什么是复制和交换习惯用法?
更好的是,使用std::vector而不是new和delete.然后,您不需要编写自己的复制构造函数或赋值运算符.
简短的回答 - 不要这样做。
细节:
// copy constructor
FeatureValue::FeatureValue(const FeatureValue& other)
{
m_size = other.m_size;
delete[] m_value; // m_value NOT INITIALISED - DON'T DELETE HERE!
m_value = new uint8_t[m_size];
for (int i = 0; i < m_size; i++)
{
m_value[i] = other.m_value[i];
}
}
// assignment operator function
FeatureValue& FeatureValue::operator=(const FeatureValue& other)
{
FeatureValue(other); // error C2082: redefinition of formal parameter
return *this;
}
Run Code Online (Sandbox Code Playgroud)
笔记:
m_value当复制构造函数开始运行时,它有一个不确定的值 - 您可以分配给它,但从中读取是未定义的行为,并且对它来说delete[]更糟糕(如果有什么比 UD 更糟糕的话!;-))。所以,忽略那一delete[]行。接下来,如果operator=尝试利用复制构造函数的功能,它必须首先释放m_value指向的任何现有数据,否则将会泄漏。大多数人尝试按如下方式执行此操作(已损坏)-我认为这就是您想要的:
FeatureValue& FeatureValue::operator=(const FeatureValue& other)
{
// WARNING - this code's not exception safe...!
~FeatureValue(); // call own destructor
new (this) FeatureValue(other); // reconstruct object
return *this;
}
Run Code Online (Sandbox Code Playgroud)
这样做的问题是,如果FeatureValue的创建失败(例如,因为new无法获得它想要的内存),那么该FeatureValue对象将处于无效状态(例如,m_value可能指向太空)。稍后,当析构函数运行并执行 a 时delete[] m_value,您会出现未定义的行为(您的程序可能会崩溃)。
你真的应该更系统地处理这个问题......要么一步步写出来,要么实现一个有保证的非抛出swap()方法(很容易做到......只是std::swap() m_size和m_value,并使用它ala:
FeatureValue& FeatureValue::operator=(FeatureValue other)
{
swap(other);
return *this;
}
Run Code Online (Sandbox Code Playgroud)
这既简单又干净,但有一些小的性能/效率问题:
将任何现有m_value数组保留的时间超过必要的时间,增加峰值内存使用...您可以调用clear(). 实际上,大多数重要的程序不会关心这一点,除非所讨论的数据结构保存大量数据(例如,PC 应用程序为数百兆字节或千兆字节)。
甚至不尝试重用现有m_value内存 - 而是总是做另一个new(other这可能会减少内存使用量,但并不总是值得的)。
最终,可能存在不同的复制构造函数的原因operator=- 而不是让编译器自动从另一个创建一个 - 是最佳高效的实现不能 - 一般来说 - 以您希望的方式相互利用。
| 归档时间: |
|
| 查看次数: |
18707 次 |
| 最近记录: |