2012-02-23 5 views
1

Рассмотрим этот код:unique_ptr указывает всегда на одной и той же области памяти

using namespace std; 

int* get() 
{ 
    unique_ptr<int> p (new int[4]); 
    return p.get(); 
} 
int main(int argc, char **argv) 
{ 
    int *arr1=get(); 
    int* arr2=get(); 
    for(int i=0;i<4;i++) 
    { 
     arr1[i]=i; 
     arr2[i]=i*2; 
    } 
    for(int i=0;i<4;i++) 
     cout << arr1[i]; 
    return 0; 
} 

arr1 и точка arr2 к одной и той же области памяти. Таким образом, они имеют одинаковые значения. я не понимаю, почему, когда я называю arr2 = Get():

unique_ptr<int> p (new int[4]); 

Этот объект не должен быть создан снова? Он не удаляется, поскольку все еще доступен arr1. Как получить два массива разных областей памяти?

+2

Как только get возвращает, p выходит из области действия и удаляет указатель. Вам нужно будет вернуть unique_ptr . – BoBTFish

+0

@BoBTFish: Хороший диагноз, плохое лечение. –

+0

Есть ли причина, по которой вы не можете использовать 'std :: array' или' std :: vector'? Оба были бы проще, чем выкладывать себя с распределением памяти. – luke

ответ

5

Я уверен, что вы играете с неопределенным поведением, которое плохо.

данные, на которые указывалось, были уничтожены, когда уникальный указатель был уничтожен, тот факт, что значения одинаковы, и один и тот же слот был удалён.

для указателей на тип массива использовать вектор

std::vector<int> get() 
{ 
    return std::vector<int>(4); 
} 

int main() 
{ 
    std::vector<int> arr1=get(); 
    std::vector<int> arr2=get(); 
    return 0; 
} 

для нормальных указателей единичных значений, то вы можете вернуть unique_ptr;

std::unique_ptr<int> get(){ 
    return std::unique_ptr<int>(new int(0)); 
} 
::: 
std::unique_ptr<int> ptr=get(); 
+1

'std :: move' здесь не требуется, есть правило, в котором говорится, что ходы автоматически используются в тех местах, где разрешено разрешение, так что это включает возвращаемые значения. –

+0

@BenVoigt круто спасибо, я думал, что это так, я вроде как вставляю их, потому что он сам документирует, демонстрируя мое намерение и рассуждая о возвращении тяжелых предметов. – 111111

+2

Кроме того, 'std :: unique_ptr' намного умнее, чем' std :: auto_ptr' когда-либо был, и теперь он определен для типов массивов ... если вы используете его с типом массива, например. 'unique_ptr '. –

0

Утечка памяти при таком использовании интеллектуальных указателей. unique_ptr будет использовать оператор delete для освобождения выделенной памяти, но вам нужно удалить []. Также возвращаемое значение функции get будет недопустимым ptr, потому что unique_ptr освободит выделенную область. Если вам нужны динамически выделенные массивы, используйте std :: vector.

+2

Это не утечка памяти, это использование памяти, которая уже освобождена. –

+0

Есть 2 проблемы, первая из которых - утечка памяти, unique_ptr будет использовать оператор delete вместо delete [] в случае распределения массива. – AlexTheo

+2

Алекс: Вы правы, это плохо, но это все еще не утечка памяти. Это неопределенное поведение, но типичная реализация вызовет неправильное количество деструкторов (что для 'int' довольно бессмысленно, так как деструктор тривиален). –