使用STL向量复制构造函数与赋值运算符
Copy constructor vs assignment operator with STL vector
有这个class:
class A
{
int number;
int number2;
public:
A(int _number):number(_number),number2(0)
{
cout<<"Normal constructor\n";
}
A()
{
cout<<"Default constructor\n";
}
A(const A& source)
{
number = source.number;
number2 = source.number2;
cout<<"Copy constructor\n";
}
A & operator=(const A& source)
{
number = source.number;
number2 = source.number2;
cout<<"Assignment operator\n";
return *this;
}
};
如果创建了 vector<A> obj {1,2,3}
,normal constructor
被调用了三次,因为它没有声明为 explicit
,因此它被用作 converting constructor
。然后 copy constructor
被调用了三次。
- 有什么方法可以在跳过复制操作的同时声明和实例化
vector
?
如果执行 vector<A> obj_1;
,将创建一个可以容纳类型 A
对象的空向量 - 没有调用构造函数,但对象存在.
- 为什么没有调用构造函数?
- 我是否声明了该对象是完全可用的?
来自 this link:
复制构造函数用于根据其他对象的数据初始化先前未初始化的对象。
赋值运算符用于用其他对象的数据替换先前初始化对象的数据。
执行 obj_1 = obj
,如果我的 obj_1 之前已初始化,则会导致在我的 class [=19= 中调用 copy constructor
而不是 operator=
函数] 如我所料?
此外,在 vector
中已经有一个 operator=
函数。我怎么知道什么时候调用每个?
vector<A> obj {1,2,3};
vector<A> obj_1;
obj_1 = obj; // Why copy constructor called instead of function operator= inside my class
Is there any way a vector
can be declared and instantiated while skipping the copying operation?
没有。当您执行 vector<A> obj {1,2,3}
时,编译器会根据提供的值创建一个 std::initializer_list<A>
。 std::initializer_list
创建是您看到三个正常构造函数调用的原因。然后 vector 必须复制这些元素,因为这些元素的底层存储是 const
。没有办法通过列表初始化来解决这个问题。即使 vector<A> obj {A(1),A(2),A(3)}
仍然会导致复制。
如果您不想那样做,您可以做的一件事是使用 reserve
为元素创建存储空间,然后使用 emplace_back
直接构造向量中的对象,例如
vector<A> obj;
obj.reserve(3);
for (int i = 1; i < 4, ++i)
obj.emplace_back(i);
Doing obj_1 = obj
, if my obj_1
was previously initialized results in calling the copy constructor instead of operator=
function inside my class A as I was expecting?
这是因为 obj_1
是空的。因为它是空的,所以没有元素可以调用赋值运算符。相反,它所做的是在 obj_1
中创建元素,这些元素是 obj
的副本,最有效的方法是只调用复制构造函数而不是默认构造对象然后分配给它们。
如果你有
vector<A> obj {1,2,3};
vector<A> obj_1 {3, 4, 5};
obj_1 = obj;
相反,您会看到使用赋值运算符代替,因为实际上有对象要分配给。
有这个class:
class A
{
int number;
int number2;
public:
A(int _number):number(_number),number2(0)
{
cout<<"Normal constructor\n";
}
A()
{
cout<<"Default constructor\n";
}
A(const A& source)
{
number = source.number;
number2 = source.number2;
cout<<"Copy constructor\n";
}
A & operator=(const A& source)
{
number = source.number;
number2 = source.number2;
cout<<"Assignment operator\n";
return *this;
}
};
如果创建了 vector<A> obj {1,2,3}
,normal constructor
被调用了三次,因为它没有声明为 explicit
,因此它被用作 converting constructor
。然后 copy constructor
被调用了三次。
- 有什么方法可以在跳过复制操作的同时声明和实例化
vector
?
如果执行 vector<A> obj_1;
,将创建一个可以容纳类型 A
对象的空向量 - 没有调用构造函数,但对象存在.
- 为什么没有调用构造函数?
- 我是否声明了该对象是完全可用的?
来自 this link:
复制构造函数用于根据其他对象的数据初始化先前未初始化的对象。
赋值运算符用于用其他对象的数据替换先前初始化对象的数据。
执行 obj_1 = obj
,如果我的 obj_1 之前已初始化,则会导致在我的 class [=19= 中调用 copy constructor
而不是 operator=
函数] 如我所料?
此外,在 vector
中已经有一个 operator=
函数。我怎么知道什么时候调用每个?
vector<A> obj {1,2,3};
vector<A> obj_1;
obj_1 = obj; // Why copy constructor called instead of function operator= inside my class
Is there any way a
vector
can be declared and instantiated while skipping the copying operation?
没有。当您执行 vector<A> obj {1,2,3}
时,编译器会根据提供的值创建一个 std::initializer_list<A>
。 std::initializer_list
创建是您看到三个正常构造函数调用的原因。然后 vector 必须复制这些元素,因为这些元素的底层存储是 const
。没有办法通过列表初始化来解决这个问题。即使 vector<A> obj {A(1),A(2),A(3)}
仍然会导致复制。
如果您不想那样做,您可以做的一件事是使用 reserve
为元素创建存储空间,然后使用 emplace_back
直接构造向量中的对象,例如
vector<A> obj;
obj.reserve(3);
for (int i = 1; i < 4, ++i)
obj.emplace_back(i);
Doing
obj_1 = obj
, if myobj_1
was previously initialized results in calling the copy constructor instead ofoperator=
function inside my class A as I was expecting?
这是因为 obj_1
是空的。因为它是空的,所以没有元素可以调用赋值运算符。相反,它所做的是在 obj_1
中创建元素,这些元素是 obj
的副本,最有效的方法是只调用复制构造函数而不是默认构造对象然后分配给它们。
如果你有
vector<A> obj {1,2,3};
vector<A> obj_1 {3, 4, 5};
obj_1 = obj;
相反,您会看到使用赋值运算符代替,因为实际上有对象要分配给。