到目前为止,我发现,我完全不了解std :: vector的本质。
让我解释一下:
矢量是可以增长的,对吗?这意味着,在内部它必须以某种方式动态分配/重新分配内存。像这样:
class vector {
private:
int *data;
};
好。但是这样的定义意味着如果我们通过引用或值将std :: vector传递给另一个函数 - 这两种类型的参数传递之间没有区别,并且两个函数都能够修改数据(除非vector是作为const传递。
BUT!我尝试了以下内容,但我的想法失败了:
void try_to_modify(vector<int> v) {
v[2] = 53;
}
int main() {
vector<int> v(3);
v[2] = 142;
try_to_modify(v);
cout << v[2] << '\n'; // output is: 142
return 0;
}
那么真相在哪里? std :: vector到底是什么?
谢谢。
答案 0 :(得分:7)
std :: vector是一个容器,它在内部管理其内存并提供自定义复制构造函数。在此复制构造函数中,将分配新内存并复制现有数据,这使其成为一项昂贵的操作。如果要传递矢量而不复制包含的数据,可以传递const引用,例如const std::vector<int>&
。
让我们看看如何实现像std :: vector这样的基本容器。
template <typename T>
class MyVector
{
public:
MyVector (int size)
: data_ (new T[size])
, size_ (size)
{}
~MyVector ()
{
delete [] data_;
}
private:
T* data_ = nullptr;
int size_ = 0;
};
如果我们复制这样的对象,我们就会遇到两个问题。首先,正如您所注意到的,内存将指向相同的位置。其次,我们将有两个析构函数将破坏相同的内存,从而实现双重释放。所以,让我们添加一个复制构造函数,每当复制时都会调用它。
MyVector (const MyVector& other)
: size_ (other.size_)
{
data_ = new T[size_];
std::copy (other.data_, other.data_ + size_, data_);
}
MyVector& operator= (const MyVector& other)
{
// allocate and copy here to allow for self-assignment
auto newData = new T[other.size_];
std::copy (other.data_, other.data_ + size_, newData);
delete [] data_;
size_ = other.size_;
data_ = newData;
return *this;
}
那就是std::vector
内部如何运作。
答案 1 :(得分:-1)
这对于vector来说不是一个问题,因为它是pass-by-value和pass-by-reference参数。
void try_to_modify (vector<int> vec)
会将原始矢量的副本发送给该函数,该函数将在副本上运行。矢量将在复制时复制数据。即指向新数据的新指针。
但是,如果您将函数定义为:void try_to_modify(vector<int> & vec)
,那么它会将精确向量发送到函数,您的函数将对其进行操作。
通过引用传递对象来说要快得多,并且通常更可取,除非您特别需要副本。