2015-05-20 4 views

ответ

7

Это не будет компилироваться, так как преобразование в shared_ptr является явным. Если бы я наивно исправил это:

foo(std::shared_ptr<T>(new T()), std::shared_ptr<T>(new T())); // don't do this 

тогда действительно есть вероятность утечки памяти. Один разрешается порядок оценки является:

T * p1 = new T(); 
T * p2 = new T(); 
std::shared_ptr<T> s1(p1); 
std::shared_ptr<T> s2(p2); 
foo(s1,s2); 

Если второй new выбрасывает исключение, то первый объект будет просочилась. Чтобы исправить это, убедитесь, что первый общий указатель инициализируется перед попыткой второго выделения, либо с временной переменной:

std::shared_ptr<T> a(new T()); 
std::shared_ptr<T> b(new T()); 
foo(a,b); 

или вызов функции для инициализации каждого

foo(std::make_shared<T>(), std::make_shared<T>()); 
+0

Да, не компилируется. Это «перевод» из кода с другой реализацией интеллектуального указателя, у которого не было явно выраженного конструктора. Но в любом случае дело было в определении порядка оценки. – Anton

2

Как сказал @ Mike, ваш источник не будет компилироваться. Вам необходимо явное построение shared_ptr, таких как:

foo(std::shared_ptr<T>(new T()), std::shared_ptr<T>(new T())); 

Это по-прежнему небезопасно. В выражениях C++ выражения, используемые в качестве аргументов функции, обычно могут быть оценены в любом порядке, включая чередование, за исключением случаев, когда другие правила ограничены.

Для одного примера, заказ может быть:

  1. выделение памяти для первого Т
  2. построить первую T
  3. выделяет память для второго Т
  4. построить вторую T
  5. построить shared_ptr
  6. построить shared_ptr

И если сбой (3) или (4) не выполнен (путем метания), объект, построенный на этапе (2), не будет разрушен, а память, выделенная на этапе (1), будет протекать.

Смежные вопросы