我有一个管理灰度图像的课程。我想用libpng保存它。为此,我想使用const
成员函数,如下所示:
void GrayscaleImage::SavePNG(std::string filename) const
{
// ...
png_bytep* row_pointers = new png_bytep[m_height];
for (int i = 0; i < height_; i++) {
row_pointers[i] = const_cast<png_bytep>(m_data.data()) + i * m_width * sizeof(uint8_t);
}
png_set_rows(png_ptr, info_ptr, row_pointers);
// ...
}
问题是png_set_rows
的第三个参数是非const的,所以我必须在某个时候使用const_cast
,如果我希望成员函数GrayscaleImage::SavePNG
为{{ 1}}。我想知道,这样做是否安全?
答案 0 :(得分:1)
libpng提供了一个API,使它可以释放row_pointers和它们指向的东西; png_data_freer。这是读取时的默认值(当前可以调用png_set_rows但忽略调用)。
只要你不打电话给png_data_freer,你所做的就是安全的。没有写API修改输入数据。
png_write_image(API png_write_png调用)中存在问题,它存在于png_write_rows中。它曾经存在于png_write_row中,这是最低级别的API,但在libpng 1.5中修复了;它是一个安静的API更改,因为它不会更改参数的类型兼容性。更新它会导致现有应用程序因类型错误而无法编译。
您很快就不会看到变化;在我认为libpng 2.0之前,不太可能以需要应用程序重写现有代码的方式更改API。
答案 1 :(得分:0)
函数定义中的const
只表示您的实例不应更改。保存到文件不应该更改您的实例,所以它没关系。
当然,png_set_rows
的第三个参数不是const
,因为它已设置。
如果你在const函数中创建,销毁或更改东西,只要它们不属于你的类就没关系。您的代码不会更改任何GrayscaleImage实例。
答案 2 :(得分:0)
这不安全。如果没有png_set_rows()
声明为const
的第三个参数,则无法保证它不会修改输入数据。
您将始终必须处理未声明参数const
的库,即使它们可以。这就是const_cast
存在的原因。你应该非常谨慎地使用它。但从描述来看,png_set_rows()
不太可能修改您的数据。
编辑:这是源代码。您可以看到它不会修改row_pointers
。 (但它肯定会修改另外两个论点!)
void PNGAPI
png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers)
{
png_debug1(1, "in %s storage function", "rows");
if (png_ptr == NULL || info_ptr == NULL)
return;
if (info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers))
png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
info_ptr->row_pointers = row_pointers;
if (row_pointers)
info_ptr->valid |= PNG_INFO_IDAT;
}