3

我想了解如何vector在 C++ 中实现。以前有一个问题问过这个,所以我看了一下,我有一个小问题。假设链接问题中的实现是正确的,让我们看一下这段代码:

int main(){
    Vector<int> test2 = test_Vector();
    cout << test2[0] << endl;
    return 0;
}


// below is NOT the STL vector object, but the one in the linked question,
// in which the asker tries to implement STL vector himself/herself 
Vector<int> test_Vector(){
    Vector<int> test;
    test.push_back(5);
    return test;
}

据我了解,test Vector对象是在本地创建的,因此当test_Vector方法返回时,本地对象超出范围,从而调用析构函数并 -delete动态数组。由于代码实际上有效并且打印了 5,我想我错了。正确的解释是什么?

4

3 回答 3

3

你是对的,但你错过了一件重要的事情。

因为您要返回 a Vector<int>,所以您应该将其视为被复制。这通常会调用复制构造函数,该构造函数复制testVector<int>. 复制构造函数在链接问题中实现为:

template<class T>
Vector<T>::Vector(const Vector<T> & v)
{
    my_size = v.my_size;
    my_capacity = v.my_capacity;
    buffer = new T[my_size];  
    for (int i = 0; i < my_size; i++)
        buffer[i] = v.buffer[i];  
}

请注意,由于返回值优化,可能不会调用复制构造函数(请参阅下面评论中的头发分裂)。在许多情况下,编译器可以优化复制,而 C++ 标准允许这种优化可能会改变程序行为

无论是复制对象,还是应用 RVO,您最终都应该得到相同的结果。如果您遵循正常的面向对象实践,优化不应破坏您的对象。

无论类型如何,您都应该始终考虑按值(即复制)传递的函数返回值,然后考虑您的编译器可能正在执行 RVO。重要的是不要忘记(或四或五)规则。

于 2013-03-20T23:13:41.090 回答
1

他提供了一个公共的复制构造函数(从技术上讲,他没有将复制构造函数设为私有),因此标准的 C++ 逻辑开始执行并制作对象的副本以返回。新对象是本地的main。在复制构造函数内部,malloc编辑新内存并复制数据。如果他没有提供复制构造函数,它将访问无效内存(尝试从已释放的指针访问内存)

于 2013-03-20T23:14:15.803 回答
1

test返回时,它的复制构造函数被调用(理论上),它分配一个新的内存块并复制test. tests 堆栈上的原始test_Vector数据被破坏(理论上)test2并被分配副本,这意味着将调用赋值运算符(理论上),它将再次分配内存并从返回时创建的临时对象复制数据。从 then 返回的临时对象test_Vector的析构函数称为(理论上)。

如您所见,如果没有编译器优化,这就是地狱 :) 如果您不做任何过于巴洛克的事情并且编译器很聪明并且您的情况就是这么简单,则可以跳过“理论上”。有关C++11 的一些更新,请参阅此内容。

于 2013-03-20T23:14:47.020 回答