我有以下代码,其中有几件事最让我感到困扰:
#include <iostream>
#include <functional>
class Samp {
char str[10] = "Default";
public:
Samp(char s[]) { strcpy(str, s); printf("Constructor\n"); }
Samp(const Samp& s) { printf("Copy Constructor\n"); }
~Samp() { printf("Destructor\n"); }
char* out() {
return str;
}
friend std::ostream& operator<<(std::ostream& stream, const Samp& s) {
stream << s.str;
return stream;
}
};
void output(Samp s) {
std::cout << s << std::endl;
}
int main(int argc, const char * argv[]) {
std::function<void(Samp s)> o;
o = output;
o((char*)"Hello");
return 0;
}
在执行时,程序将提供以下输出
Constructor
Copy Constructor
Default
Destructor
Destructor
Program ended with exit code: 0
答案 0 :(得分:5)
perfect forwarding将std::function
调用的参数传递给存储在std::function
对象内部的可调用对象。
因此o(args...)
的行为与output(args...)
不同。相反,它与:
output( std::forward<Args...>(args...) );
或者在这个具体示例中,
output( std::forward<Samp>( (char *)"Hello" ) );
在此示例中,我们看到“完美”的转发不是那么完美,因为此代码的行为与output( (char *)"Hello" );
略有不同。
为forward
选择的重载的签名为Samp&& forward(Samp&& arg);
。因此,对于arg
,必须有一个临时实体才能绑定到std::forward
;那就是您看到的“构造函数”。
然后,“复制构造函数”是根据output
的返回值初始化std::forward
函数的参数。如果Samp
具有移动构造函数,则可能是移动操作。
答案 1 :(得分:2)
您的类的构造方法和复制方法基本上在一个地方调用。 使用您的函数时,将通过构造创建Samp S,然后将其复制到void fnc。
答案 2 :(得分:2)
void output(Samp s)
这是问题所在。此函数按值传递对象。致电
o((char*)"Hello")
,它将通过默认构造函数创建一个临时的Samp对象,并通过复制构造函数创建另一个新对象以传递给该函数。