Я использую библиотеку gsl в C ++. Я объявил сетку указателя gsl_vector как закрытый член класса.
private:
gsl_vector * mesh;
У меня также есть метод, MeshBuilder, который объявляет gsl_vector, указатель сетки (переопределяя исходную переменную сетки) и возвращает сетку.
gsl_vector * ThinFilm::LinearMesh(...){
gsl_vector * mesh = gsl_vector_alloc(numberofcells);
...
return mesh;
}
Затем я присваиваю результат метода переменной mesh как:
mesh = MeshBuilder(...);
Он компилируется и работает просто отлично (без предупреждений, с -Wall). Проходя по программе, я заметил, что переменной меш назначается адрес, а затем MeshBuilder перезаписывает его. Именно это я и запрограммировал.
Но разве это хорошая практика? В конце концов, разве я не должен присваивать значение адресу указателя?
Разве я не должен вместо этого объявлять указатель меша в методе MeshBuilder и, следовательно, напрямую использовать указатель, объявленный в закрытом разделе класса?
Я предполагаю, что единственная причина, по которой это работает, заключается в том, что значение адреса, которое я назначаю для меша, действительно является действительным, так как оно было объявлено.
Переменная mesh в методе затеняет переменную private.
Если вы используете приватную переменную напрямую, вы избегаете объявления временной переменной, но на практике она не сильно меняется.
Однако, если интерфейс класса должен использоваться в многопоточных контекстах, то непосредственное изменение закрытой переменной сделает ее видимой для любого другого потока в распределение время, так что если ...
section в приведенном выше коде выполняет какую-то настройку вектора, это означает, что другой поток может увидеть или использовать недопустимую (не сконструированную) переменную.
В этом случае вы должны использовать временный (как в вашем исходном коде) и защитить назначение mesh = MeshBuilder(...)
с мьютексом или атомарной операцией (например, CAS или обмен указателями).
Кроме того, во всех случаях, если вы хотите написать безопасный код, вы также должны учитывать, что произойдет, если в ...
часть кода.
Устанавливая приватную переменную напрямую, вы можете иметь возможность очистить выделение (в деструкторе вашего класса), иначе вы получите утечку памяти, так как указатель не очищает выделение самостоятельно.
Если вы хотите действительно безопасный код, работающий во всех возможных условиях, вы должны использовать умный указатель вместо временного (для безопасного кода исключения), мьютекса для защиты доступа к частным переменным (для многопоточного безопасного кода).
Простой ответ — нет, в вашем текущем коде вы пропускаете ресурс.
Проблема в gsl_vector_alloc
не возвращает значение, но на самом деле адрес, который указывает на структуру, которая содержит значение, кроме вас, чтобы увидеть. В данном контексте, gsl_vector_alloc
ведет себя похоже на использование new
, так как он выделяет векторную структуру и инициализирует ее.
Функция gsl_vector_alloc
Как следует из названия предложить выделить вектор. Это означает, что вам нужно освободить его с gsl_vector_free
прежде чем вы переопределите это.
В таком случае также может произойти сбой выделения gsl_vector_alloc
вернусь NULL
и вам придется проверить это, прежде чем использовать сетку.
Примечание: в функции, которую вы предоставляете, вы вызываете свою локальную переменную mesh, имя которой совпадает с именем частного члена, это плохая практика, поскольку локальная переменная скрывает закрытый член.