这个成语是什么,什么时候应该使用?它解决了哪些问题?当使用C++ 11时,成语是否会改变?
虽然在许多地方已经提到过,但我们没有任何单一的"它是什么"问题和答案,所以在这里.以下是前面提到的地方的部分列表:
c++ c++-faq copy-constructor assignment-operator copy-and-swap
我知道C++编译器为类创建了一个复制构造函数.在这种情况下,我们必须编写用户定义的复制构造函数吗?你能举一些例子吗?
如果我覆盖operator=,复制构造函数会自动使用new运算符吗?同样,如果我定义了一个拷贝构造函数,会operator=自动"继承"拷贝构造函数的行为吗?
c++ constructor operators copy-constructor assignment-operator
复制构造函数的这种实现有一些缺点吗?
Foo::Foo(const Foo& i_foo)
{
*this = i_foo;
}
Run Code Online (Sandbox Code Playgroud)
我记得,在某些书中建议从赋值运算符调用复制构造函数并使用众所周知的交换技巧,但我不记得了,为什么......
我有一个类,需要一个非默认的复制构造函数和赋值运算符(它包含指针列表).有没有通用的方法来减少复制构造函数和赋值运算符之间的代码重复?
由于某种原因,我不得不为我的班级提供复制构造函数和operator =.operator=如果我定义了一个副本ctor,我想我不需要,但是QList想要一个.把它放在一边,我讨厌代码重复,所以这样做有什么不对吗?
Fixture::Fixture(const Fixture& f) {
*this = f;
}
Fixture& Fixture::operator=(const Fixture& f) {
m_shape = f.m_shape;
m_friction = f.m_friction;
m_restitution = f.m_restitution;
m_density = f.m_density;
m_isSensor = f.m_isSensor;
return *this;
}
Run Code Online (Sandbox Code Playgroud)
只是出于好奇,没有办法切换它,以便大部分代码都在复制文件中并operator=以某种方式利用它?我尝试过,return Fixture(f);但不喜欢那样.
看来我需要更清楚地说明复制构造函数和赋值运算符已被我继承的类隐式禁用.为什么?因为它是一个抽象的基类,不应该自己实例化.然而,这门课程是独立的.
背景: 我有一个复杂的类,有很多变量.我有一个声音和测试的复制构造函数:
Applepie::Applepie( const Applepie ©) :
m_crust(copy.m_crust),
m_filling(copy.m_filling)
{
}
Run Code Online (Sandbox Code Playgroud)
在初始化列表中调用的一些成员变量复制构造函数执行分配.
问题:
我需要创建operator=.我可以简单地执行以下操作,而不是使用赋值而不是初始化列表复制现有的构造函数,释放正在被替换的内存等等,
Applepie& Applepie::operator=( const Applepie ©)
{
if( this != ©)
{
this->~Applepie(); // release own object
new(this) Applepie(copy); // placement new copy constructor
}
return *this;
}
Run Code Online (Sandbox Code Playgroud)
换句话说,是毁灭自我后跟一个放置新的复制构造函数在语义上与operator =?
这似乎有可能大大减少重复代码并确认每个变量都已正确初始化,但代价是在分配期间可能会略微降低效率.我错过了一些更加模糊的东西吗?
理由: 我的实际班级有大约30个变量.我担心我的复制构造函数和我的赋值操作符都必须复制所有三十个,并且代码可能会发散,导致两个操作以不同的方式执行操作.
随着最近C++类的使用越来越多,std::unique_ptr我发现很多默认情况下无法复制使用它们的成员.这很好,因为它们无法复制:如果父类必须是可复制的,则需要明确地处理这些成员.
但是我发现重载复制构造函数/运算符不方便.每个成员都需要明确复制,即使是那些不需要特殊处理的成员.更重要的是,当添加成员时,代码维护者必须记住将此成员添加到复制功能中.我发现这个代码维护者未能做到这一点的可能性接近于我的那个.(我知道至少有一个可以让operator = 依赖于复制构造函数).
所以我想知道是否有有效的方法来重载复制构造函数/运算符,这样就不需要为默认复制的成员编写代码.
我能想到的一个解决方案是将类拆分为两个:放入一个默认复制的基类成员,其余放在子类中; 仅限子类的重载副本.我觉得这有点不雅,我相信它有缺点.
另一种方法是将非可复制对象包装到类中,这些类在复制时构造底层的非可复制对象.这可能更好,但只有当这些对象可以独立于其他父类成员进行初始化时才有用.
如果有人有想法或经验分享他们如何处理这个或不是复制,我会很高兴听到它.
我正在努力学习C++中的"三巨头"..我设法为"三巨头"做了非常简单的程序..但我不知道如何使用对象指针..以下是我的第一次尝试.
当我写这篇文章时,我有一个疑问......
问题
我是否正确地说我需要删除析构函数中的指针?
class TreeNode
{
public:
TreeNode();
TreeNode(const TreeNode& node);
TreeNode& operator= (const TreeNode& node);
~TreeNode();
private:
string data;
TreeNode* left;
TreeNode* right;
friend class MyAnotherClass;
};
Run Code Online (Sandbox Code Playgroud)履行
TreeNode::TreeNode(){
data = "";
}
TreeNode::TreeNode(const TreeNode& node){
data = node.data;
left = new TreeNode();
right = new TreeNode();
left = node.left;
right = node.right;
}
TreeNode& TreeNode::operator= (const TreeNode& node){
data = node.data;
left = node.left;
right = node.right;
return *this;
}
TreeNode::~TreeNode(){
delete …Run Code Online (Sandbox Code Playgroud) 有没有办法让我可以使复制构造函数和赋值运算符的主体包含相同的代码,而实际上没有重复的代码(函数头除外)?
c++ constructor code-duplication copy-constructor assignment-operator
在互联网上有很多代码可以解释(特别是在这里,在stackoverflow上)*this.
例如,来自复制构造函数和C++中的=运算符重载:可能是一个常见的函数吗?:
MyClass& MyClass::operator=(const MyClass& other)
{
MyClass tmp(other);
swap(tmp);
return *this;
}
Run Code Online (Sandbox Code Playgroud)
当我把swap写为:
void MyClass::swap( MyClass &tmp )
{
// some code modifying *this i.e. copying some array of tmp into array of *this
}
Run Code Online (Sandbox Code Playgroud)
是不是足够设定返回值operator =,以void避免回国*this?
可能重复:
三个规则是什么?
如何std::pair为其组件调用析构函数?我正在尝试将类的实例添加到a std::map,但是我的类的析构函数出错了.
我已经将我的问题/问题缩小到以下非常简单的例子.
下面,my_class仅int在构造时创建一个数组,并在销毁时删除它.不知何故,我得到一个"双删除"错误:
//my_class.h
class my_class {
public:
int an_int;
int *array;
//constructors:
my_class()
{
array = new int[2];
}
my_class(int new_int) : an_int(new_int)
{
array = new int[2];
}
//destructor:
~my_class()
{
delete[] array;
}
}; //end of my_class
Run Code Online (Sandbox Code Playgroud)
与此同时,在main.cpp ...
//main.cpp
int main(int argc, char* argv[])
{
std::map<int, my_class> my_map;
my_map.insert( std::make_pair<int, my_class> (1, my_class(71) ) );
return 0;
} // end main
Run Code Online (Sandbox Code Playgroud)
编译很顺利,但这会产生以下运行时错误:
*** glibc detected *** …Run Code Online (Sandbox Code Playgroud) 我有一个结构,Foo,指针数组为Bar.
struct Foo
{
Bar* _BarList;
Foo()
{
_BarList = new Bar[1];
_BarList[0] = Bar(10, 20);
}
Foo& operator=(const Foo& foo)
{
Bar* tmpBarList = new Bar[1];
tmpBarList[0] = foo._BarList[0];
delete[] _BarList;
_BarList = tmpBarList;
return *this;
}
~Foo()
{
delete[] _BarList;
}
};
Run Code Online (Sandbox Code Playgroud)
我这样称呼它
Foo baz = fooFunc();
Run Code Online (Sandbox Code Playgroud)
(似乎)如果我在函数(fooFunc)中创建一个Foo(f)实例并返回它,则在返回值之前调用析构函数,因为我丢失了_BarList的内容.
这在函数中创建是有意义的.这是一个例子.
Foo fooFunc()
{
Foo f = Foo();
return f;
}
Run Code Online (Sandbox Code Playgroud)
如果我在返回时直接返回Foo的实例,则直到调用了equals运算符之后才调用该项的析构函数(通过调用行上的equals语句).
Foo fooFunc()
{
return Foo();
}
Run Code Online (Sandbox Code Playgroud)
我想这是有道理的,因为我在对象中创建Foo,并且在返回对象之前清除了一些东西.
我想我可以通过这样做返回来解决这个问题(在编写一个新的构造函数来获取Foo之后):
Foo fooFunc()
{
Foo f = Foo();
return Foo(f);
} …Run Code Online (Sandbox Code Playgroud) c++ ×13
constructor ×2
c++-faq ×1
destructor ×1
dry ×1
map ×1
operators ×1
return-value ×1
std-pair ×1
this ×1