C++中的统一初始化会导致运行时错误。

5

我非常喜欢使用统一初始化,当我想要构造初始化的变量时,我在大多数情况下都会使用它。最近,在构造类型为cv::Mat的变量时,我遇到了奇怪的错误。

cv::Mat lookUpTable( 1, 256, CV_8U );
uchar* p = lookUpTable.ptr();

for( int i = 0; i < 256; ++i )
{
    p[i] = cv::saturate_cast<uchar>( pow( i / 255.0, gamma ) * 255.0 );
}

虽然这种实现方式表现良好,但如果使用统一初始化,则可能会出现问题。

cv::Mat lookUpTable{ 1, 256, CV_8U };

出现以下错误:

malloc_consolidate(): invalid chunk size

我仍然不确定发生了什么。是否使用了不同的构造函数(而非预期的)?请有人进一步解释一下吗?


似乎统一初始化带来的负面影响大于好处。 - Slava
6
我想知道在此之后,你是否仍然会认为自己是一名统一初始化的粉丝。 :P - HolyBlackCat
相关 https://dev59.com/IpDea4cB1Zd3GeqPeKLp - Slava
@HolyBlackCat 希望你不再是那么狂热的粉丝了。 - Slava
2个回答

11

cv::Mat lookUpTable{ 1, 256, CV_8U } 调用的是不同于 cv::Mat lookUpTable( 1, 256, CV_8U ) 的构造函数。 cv::Mat lookUpTable{ 1, 256, CV_8U }直接列表初始化,由于cv::Mat有一个接受std::initlizer_list的构造函数,因此将调用该构造函数而不是第一次调用所执行的3个参数的构造函数。这意味着你会得到一个包含元素{ 1, 256, CV_8U }的矩阵,而不是一个包含256个元素的矩阵。

Nicolai Josuttis在CppCon2018上有一个非常好的关于统一初始化的“一致性”讲座:https://www.youtube.com/watch?v=7DTlWPgX6zs


6
使用{...}构造对象称为"列表初始化"cv::Mat提供了一个接受std::initializer_list的构造函数: https://github.com/opencv/opencv/blob/master/modules/core/include/opencv2/core/mat.hpp#L1007重载决议中有一个特殊规则,如果使用列表初始化,则始终优先考虑接受std::initializer_list的构造函数,而不考虑可能需要更少隐式转换的其他构造函数的存在。
调用cv::Mat(...)cv::Mat{...}完全不同。
我的心理模型是:如果要构建的对象是容器,则{...}(...)的行为可能会有所不同,因此您应该小心。否则,请优先使用{...}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接