看个构造函数创建隐式对象作为参数的例子
#include<iostream>
using namespace std;
class A
{
int a;
int b;
public:
A() { cout << "构造函数" << endl; };
A(int, int) { cout << "int构造函数" << endl; };
A(const A &) { cout << "复制构造函数" << endl; };
void operator()(int a, int b) { cout << "重载()运算符函数" << endl; }
void sum() { cout << "Sum运算符函数" << endl; }
};
void set(A visit) {
visit(1, 2);
}
int main()
{
A a = A();
set( a );
cout << endl;
A *b = new A(1,2);
A *c = new A;
A *d = new A();
b->sum();
c->sum();
d->sum();
delete b, c, d;
cout << endl;
set(A());
return 0;
}
set_1( A()); 这个的话就是调用构造函数创建了个临时对象
Yes. The manner in which you are constructing the object in the line:
set(A());
is called functional notation type conversion. This is specified in the section on constructors.
A functional notation type conversion can be used to create new objects of its type. [Note: The syntax looks like an explicit call of the constructor. —end note]
An object created in this way is unnamed.
set(A());
被称为功能符号类型转换。 这在构造函数一节中指定。
功能表示法类型转换可用于创建其类型的新对象。 [注意:语法看起来像构造函数的显式调用。 - 尾注]
以这种方式创建的对象是未命名的。
在《C++ primer plus》的P709页出现了相同的内容,解释为有构造函数调用创建的一个匿名对象。
A constructor is used to initialize objects of its class type. Because constructors do not have names, they are never found during name lookup; however an explicit type conversion using the functional notation will cause a constructor to be called to initialize an object. [ Note: The syntax looks like an explicit call of the constructor. — end note ]
complex zz = complex(1,2.3);
cprint( complex(7.8,1.2) );
构造函数用于初始化其类类型的对象。 因为构造函数没有名称,所以在名称查找期间永远不会找到它们; 但是,使用函数表示法的显式类型转换将导致调用构造函数来初始化对象。 [注意:语法看起来像构造函数的显式调用。]
complex zz = complex(1,2.3);
cprint( complex(7.8,1.2) );
以这种方式创建的对象是未命名的。
使用函数表示法的显式类型转换:
If the initializer is a parenthesized single expression, the type conversion expression is equivalent (in definedness, and if defined in meaning) to the corresponding cast expression ([expr.cast]). If the type is (possibly cv-qualified) void and the initializer is (), the expression is a prvalue of the specified type that performs no initialization. Otherwise, the expression is a prvalue of the specified type whose result object is direct-initialized ([dcl.init]) with the initializer. For an expression of the form T(), T shall not be an array type.
如果初始值设定项是带括号的单个表达式,则类型转换表达式与相应的强制转换表达式([expr.cast])等效(在定义中,如果在意义上定义)。如果类型是(可能是CV限定符)void并且初始化程序是(),则表达式是指定类型的纯右值,它不执行初始化。否则,表达式是指定类型的纯右值,其结果对象使用初始化程序进行直接初始化([dcl.init])。对于T()形式的表达式,T不应是数组类型。
CV-qualifiers有三种:const-qualifier(const限定符)、volatile-qualifier(volatile限定 符)、以及const-volatile-qualifier(const-volatile限定符)。
glvalue(泛左值) = lvalue (传统意义上的左值)+ xvalue(消亡值,通过右值引用产生)
rvalue (传统意义上的右值) = prvalue(纯右值) + xvalue
https://timsong-cpp.github.io/cppwp/n4618/expr.type.conv
感谢P.W老哥的回答。
看一些其它对象作为参数和返回值的例子放松下:
int main()
{
PriorityQueue pq1();
pq1.insert(3); // doesn't compile
PriorityQueue pq2 = PriorityQueue();
pq2.insert(3); // compiles
}
因为PriorityQueue pq1(); 将被当做是函数体,PriorityQueue返回值类型,pq1是函数名。
#include <iostream>
using namespace std;
class human
{
public:
human(){ human_num++;};
static int human_num;
~human()
{
human_num--;
print();
}
void print()
{
cout <<"human num is: " <<human_num <<endl;
}
protected:
private:
};
int human::human_num = 0;
human f1(human x)
{
x.print();
return x;
}
int main(int argc, char* argv[])
{
human h1; //调用human构造函数
h1.print(); //打印:1
human h2 = f1(h1);//完成一下动作:
//1 调用默认拷贝构造函数,参数传入
//2 在f1中打印:1
//3 创建临时对象,调用默认拷贝构造函数并初始化h2
//4 离开f1,销毁函数内对象,调用析购函数,打印 0
h2.print(); //打印 0
return 0;
} //销毁h1,h2,调用两次析构函数。