[英]What's the difference between using an Assignment Constructor vs. normal assignment here?
我花了一些时间试图理解一些 C++ 代码,并且我有 C 和 Java 的背景。有问题的代码使用了一些我有一段时间不认识或不理解的速记。 我现在知道他们正在使用赋值构造函数来分配变量,这两者都不存在。
这是示例:
cv::Mat rgb(raw_h1 + raw_h2, raw_w1, CV_8UC3);
大致相当于我发现:
cv::Mat rgb = cv::Mat(raw_h1 + raw_h2, raw_w1, CV_8UC3);
起初我不知道我在看什么,但通过调试我知道效果是什么。
稍后,我们有类似的一段新代码:
cv::Mat dst_roi = rgb(cv::Rect(0, 0, raw_w1, raw_h1));
这似乎是调用 cv::Mat 构造函数的简写:
Mat(const Mat& m, const Rect& roi);
大致等效的语句是:
cv::Mat dst_roi = cv::Mat(rgb, cv::Rect(0, 0, raw_w1, raw_h1));
事实上,用后者替换前者代码不会引入编译器错误,所以我很可能在这里找到了一些东西。
这第二个简写叫什么,您可以在已声明的 object 上调用构造函数以将 object 用作 object class 的构造函数中的参数?
为什么要使用这种形式的赋值构造函数而不是我所展示的其他赋值方法? 跟速度有关吗? 简明? 或者我自己不了解的东西?
如果我的任何假设不正确,请不要害怕指出,但至少在第一个假设上,我已经能够测试并验证我是正确的。
您的转换不正确。
cv::Mat rgb(raw_h1 + raw_h2, raw_w1, CV_8UC3); // (1)
cv::Mat dst_roi = rgb(cv::Rect(0, 0, raw_w1, raw_h1)); // (2)
(2)
实际上调用cv::Mat::operator()(const Rect &)
返回一个新的cv::Mat
。
一个简单的经验法则:
1:当您声明 object 时,将调用构造函数。
// Variable `rgb` declared.
// Thus constructor used.
cv::Mat rgb(raw_h1 + raw_h2, raw_w1, CV_8UC3);
虽然这个声明看起来像一个赋值,但它仍然是一个构造。
// In the old days, this could have been a construction (of a temporary)
// followed by a copy construction into the `rgb` object (from the temporary)
//
// Even in the old days, the standard allowed for the optimization by
// elision of the copy construction and all (majority of) the compilers used to
// implement that optimization; so the standard was updated to require
// the elision. So this is now just a normal constructor.
cv::Mat rgb = cv::Mat(raw_h1 + raw_h2, raw_w1, CV_8UC3);
2:如果不是声明,那么就是赋值。
// You don't have any examples above.
//
// Here we have construction of a temporary object.
// Followed by assignment of that object to rgb.
rgb = cv::Mat(raw_h1 + raw_h2, raw_w1, CV_8UC3);
3:任何在 object(不是类型)上使用大括号()
的东西。 不是调用构造函数,而是像函子(类似对象的函数)一样使用 object。
// rgb is an object.
// So `rgb(......)` is a functor call.
// Which means the type `cv::Mat` must define the operator()
cv::Mat dst_roi = rgb(cv::Rect(0, 0, raw_w1, raw_h1));
作为旁注:这就是为什么我总是用首字母大写字母定义我的类型,而对象/函数总是有一个首字母小写字母。 这样我就可以判断它是仿函数/函数调用还是 object 构造。
// Common conventions using initial capital letter for user defined types.
auto a = abc(1,23); // function/functor call.
auto b = Abc(1,23); // object creation.
以前使用赋值形式T var = T(a, b, c)
会创建一个T object,然后调用T的拷贝构造函数将其拷贝到var中; 而形式T var(a, b, c)
不需要副本。
如今(C++ 17 之后),强制复制省略意味着删除了对复制构造函数的调用,因此没有区别。
更多信息: https://en.cppreference.com/w/cpp/language/copy_elision
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.