在本文中,我们将给您介绍关于PHP从构造函数获取返回值的详细内容,并且为您解答php中构造函数的相关问题,此外,我们还将为您提供关于c–复制构造函数与返回值优化、C#异步执行带有返回值和参数的方法,且
在本文中,我们将给您介绍关于PHP从构造函数获取返回值的详细内容,并且为您解答php中构造函数的相关问题,此外,我们还将为您提供关于c – 复制构造函数与返回值优化、C#异步执行带有返回值和参数的方法,且获取返回值、C#构造函数、私有构造函数、静态构造函数与构造函数执行顺序、C++ 基础知识(八)--- 函数返回值(返回值,返回指针,返回对象,返回引用)--- 引用 --- 复制构造函数(拷贝构造函数)--- 深复制与浅复制的知识。
本文目录一览:- PHP从构造函数获取返回值(php中构造函数)
- c – 复制构造函数与返回值优化
- C#异步执行带有返回值和参数的方法,且获取返回值
- C#构造函数、私有构造函数、静态构造函数与构造函数执行顺序
- C++ 基础知识(八)--- 函数返回值(返回值,返回指针,返回对象,返回引用)--- 引用 --- 复制构造函数(拷贝构造函数)--- 深复制与浅复制
PHP从构造函数获取返回值(php中构造函数)
我很困惑,我有一个带有构造函数的PHP类:
class Test {
public function __construct() {
return "some text";
}
}
然后我实例化了一个对象:
$t = new test();
我希望$t的内容是“一些文本”:
print_r($t);
但它是:
Test Object
(
)
如何从构造函数中获取返回值“some text”?
解决方法:
您无法从构造函数返回任何内容. new关键字将始终生成一个新对象,从构造函数返回的内容无关紧要.
c – 复制构造函数与返回值优化
这是标准所要求的,还是可以通过构建’赋值’变量来优化函数,即使在函数体内也是如此?
struct C { int i; double d; }; C f( int i,int d ) { return C(i,d); // construct _and_ copy-construct? } int main() { C c = f( 1,2 ); }
解决方法
>构造一个本地临时,复制 – 构造它到一个返回值,并将返回值复制 – 构造到本地“c”.要么>构造一个本地临时和复制构造到“c”.要么>使用参数“i,d”构造“c”
C#异步执行带有返回值和参数的方法,且获取返回值
很多时候需要用到这些小知识点,做做笔记一起成长
下面是需要异步执行的方法
//获取所有的邮件
private List<EmailModel> GetEmailOnlyCount(POP3_ClientMessageCollection pOP3Collection)
{
int i = 0;
List<EmailModel> list = new List<EmailModel>();
foreach (POP3_ClientMessage message in pOP3Collection)
{
byte[] bytes = System.Text.Encoding.Default.GetBytes(message.HeaderToString());
Mail_Message mail_Message = Mail_Message.ParseFromByte(bytes);
EmailModel emailModel = new EmailModel()
{
EmailFrom = mail_Message.From.ToString(),
EmailDate = mail_Message.Date.ToString(),
EmailSubject = mail_Message.Subject.ToString(),
};
list.Add(emailModel);
//异步线程中,改变主线程中的控件属于跨线程的调用,需要利用代理方法
textBox5.Invoke(showProcessDelegate, "已经读取" + (++i) + "/" + pOP3Collection.Count + "封邮件");
}
return list;
}
我们需要执行以上的方法,异步中执行由于带有参数,所以我们需要代理这个方法,用一个变量来代替这一个方法,并且声明异步方法执行结束的回调方法
private delegate List<EmailModel> GetMailDelegate(POP3_ClientMessageCollection pOP3_ClientMessage);
private GetMailDelegate getMailDelegate = new GetMailDelegate(GetEmailOnlyCount);
private AsyncCallback asyncCallback;//执行完的回调方法,异步方法执行完后执行的方法
接着我们在需要执行此方法的地方,开始异步执行此方法,当然是利用代理方法执行
getMailDelegate.BeginInvoke(pOP3_ClientMessageCollection, asyncCallback, null);
等异步方法执行完之后我们需要在回调方法之中结束异步操作所以我们需要在asynCallBack之中进行操作
这里我们就是获取异步执行的方法的返回值的地方
asyncCallback = delegate (IAsyncResult result)
{
EmaliList = getMailDelegate.EndInvoke(result);//关闭异步,并且获取到方法的返回值
for (int i = EmaliList.Count; i > 0; i--)
{
ListViewItem listViewItem = new ListViewItem();
listViewItem.Text = EmaliList[i - 1].EmailFrom;
listViewItem.SubItems.Add(EmaliList[i - 1].EmailSubject);
listViewItem.SubItems.Add(EmaliList[i - 1].EmailDate);
listViewItem.SubItems.Add(EmaliList[i - 1].AttchmentsCount.ToString());
listView1.Invoke(showListViewDelegate, listViewItem);
}
};
好了,这里我们的邮箱的异步读取邮件的操作就基本完成了=v=
C#构造函数、私有构造函数、静态构造函数与构造函数执行顺序
https://www.cnblogs.com/ArtofDesign/p/3603986.html
默认构造函数,如果没有为类指定任何构造函数,编译器会自动为类创建一个无参构造函数,用以初始化类的字段;如果为类编写了构造函数,那么编译器就不会再自动生成无参构造函数了。ps.C#不允许用户为结构定义无参构造函数。
静态构造函数,不能访问实例成员,只能用来初始化一些静态字段或者属性,仅在第一次调用类的任何成员时自动执行,不带访问修饰符,不带任何参数,每个类只能有一个静态构造函数,但可以同时还有一个无参实例构造函数,如下。
public class Demo
{
static Demo() { }
public Demo() { }
}
私有构造函数,将构造函数申明为私有的,则不能通过new运算符在外部代码中实例化(但可以编写一个静态方法或属性在其内部实例化一个对象,再将结果返回给外部代码)。私有构造函数的作用:
- 永远不会实例化,因为它仅用作某些静态成员的容器
- 希望类只能通过调用某个静态方法来实例化(即所谓的对象实例化的类工厂方法)

public class Demo
{
private Demo() { }
public static Demo NewDemo()
{
return new Demo();
}
}

构造函数执行顺序,通常情况下:构造函数先调用System.Object的构造函数,再按照继承的层次结构从上往下进行,直到最终要实例化的类为止,即最先调用的是基类的构造函数,但如果类有静态构造函数,且为首次调用该类,则先调用的是子类的静态构造函数,再是父类的静态构造函数,当然静态构造函数只会执行这一次,如下

//父类
public class SuperClass
{
static SuperClass()
{
Console.WriteLine("Super.Static");
}
public SuperClass()
{
Console.WriteLine("Super.Instance");
}
}
//子类
public class ChildClass : SuperClass
{
static ChildClass()
{
Console.WriteLine("Child.Static");
}
public ChildClass()
{
Console.WriteLine("Child.Instance");
}
}
//客户程序
class Program
{
static void Main(string[] args)
{
ChildClass cc = new ChildClass();
Console.ReadKey();
}
}

输出结果为:
Child.Static
Super.Static
Super.Instance
Child.Instance
在不考了静态构造函数的情况下(因为静态构造仅执行一次,且定义静态构造函数的时候并不多),子类在调用父类的构造函数时,默认情况是调用父类的无参构造函数,如果父类只有带参构造函数,而没有无参构造函数,那么编译时会报错;不过我们可以通过base关键字来指定调用带参构造函数,如下

//父类
public class SuperClass
{
public SuperClass(string param)
{
Console.WriteLine("Super:" + param);
}
}
//子类
public class ChildClass : SuperClass
{
public ChildClass(string param):base(param)
{
Console.WriteLine("Child:" + param);
}
}
//客户程序
class Program
{
static void Main(string[] args)
{
ChildClass cc = new ChildClass("param");
Console.ReadKey();
}
}

输出结果为
Super:param
Child:param
public class SuperStaticConstructor
{
public SuperStaticConstructor()
{
Console.WriteLine("parent constructor");
}
static SuperStaticConstructor()
{
Console.WriteLine("parent static constructor");
}
}
public class StaticConstructor: SuperStaticConstructor
{
public StaticConstructor()
{
Console.WriteLine("child constructor");
}
static StaticConstructor()
{
Console.WriteLine("child static constructor");
}
}
public class StaticConstructorTest
{
public static void Run()
{
string[] strArray = new string[4]{ "a","b", "a", "b" };
Parallel.ForEach(strArray, (item) =>
{
Console.WriteLine(item);
new StaticConstructor();
});
}
}
StaticConstructorTest.Run();
C++ 基础知识(八)--- 函数返回值(返回值,返回指针,返回对象,返回引用)--- 引用 --- 复制构造函数(拷贝构造函数)--- 深复制与浅复制
一、函数返回值
1. 返回值:
int test ()
{
int a=1;
return a;
}
- 返回值时最简单的方式,它的操作主要在栈上,变量 a 在函数结束后会删除,为了返回 a 的值,系统会在内部建立一个临时变量保存 a 的值,以返回给调用该函数的表达式,调用结束后变量便不再存在。如果 a 是简单地数据类型也无所谓,不是很占用内存,如果 a 是大的自定义类型的数据,那么对 a 的复制将会占用比较大的内存。函数返回值是右值,不能进行运算符操作。
2. 返回指针:
-
int *test2() { int *b=new int(); *b=2; return b; }
- 返回指针是在 C 中除了返回值以外的唯一方式,根据函数栈的特性,也会产生复制,只是复制的是一个指针即一个地址,对于返回大型对象可以减少不少的资源消耗。但返回指针的资源的清理交给了调用者,这违反了谁申请谁销毁的原则。指针也是右值同样无法操作。
3. 返回引用:
-
int& test2() { int *b=new(); *b=2; return b; }
- 引用是值的别名,和指针一样不存在对大对象本身的复制,只是引用别名的复制。引用是左值,可以直接进行操作,也可以进行连续赋值,最经典的实例是拷贝构造函数与运算符重载一般都返回引用。
- 需要注意的是局部变量不能作为引用返回。
- C++ 中成员函数返回对象与返回引用
- 返回对象与返回引用的区别:函数原型与函数头
- Car run (const Car&)// 返回对象
- Car& run (const Car&)// 返回引用
- 返回对象涉及到生成对象的副本。因此返回对象的成本包括了调用复制构造函数来生成副本所需要的时间和调用析构函数删除副本所需要的时间。返回引用可以节省时间和内存。直接返回对象与函数直接 return a 返回值一样。都会生成临时副本。
- 返回对象与返回引用的区别:函数原型与函数头
二、C++ 中的引用
1. 引用的引入:
参数的传值方式在函数域中为参数重新分配内存,而把实参的数值传递到新分配的内存中,它的优点是可以有效避免函数的副作用。
当要求改变实参的值的时候,如果实参是一个非常复杂的对象,重新分配内存会引起程序的执行效率的下降。便引出了引用。
2. 引用的定义:
类型 & 引用变量名 = 已经定义过的变量名。
主要用于函数之间的数据传递。对于数组只能引用数组元素,不能引用数组本身(数组本身为地址)
3. 引用的使用
- 引用作为函数的参数(形参),采用引用调用时,将对实参进行操作
- 引用作为函数的返回值。一般函数返回值时,要生成一个临时变量作为返回值的副本,而采用引用作为返回值时,不生成值的副本。采用引用返回方式时,不再是返回表达式的值,而是变量。同时返回的不能是函数中的局部变量,这时返回的局部变量的地址已经失效。引用方式返回最常用的是由引用参数传递过来的变量,其次是全局变量,这样返回的变量地址才是有效的
- 返回值为引用的函数作为左值
- 代码示例 1:引用作为函数的形参
-
1 void swap(double & d1,double & d2) 2 { 3 double temp ; 4 temp=d1 ; 5 d1=d2 ; 6 d2=temp ; 7 } 8 9 int main(void) 10 { 11 double x , y ; 12 cout<<"请输入x和y的值" 13 <<''\n''; 14 cin>>x>>y ; 15 swap(x,y) ; 16 cout<<"x="<<x<<''\t'' 17 <<"y="<<y<<''\n''; 18 return 0; 19 }
- 代码示例 2 引用作为返回值
-
1 double temp; //全局变量 2 double fsqr1(double a) 3 { 4 temp=a*a ; return temp; 5 } 6 7 double & fsqr2(double a) 8 { 9 temp=a*a ; return temp; 10 } 11 12 int main() 13 { 14 double x=fsqr1(5.5); //第一种情况 15 double y=fsqr2(5.5); //第二种情况 16 cout<<"x="<<x<<''\t‘<<"y="<<y<<endl; 17 return 0; 18 }
fsqr1先是将temp值赋值给内存中建立的无名临时变量,回到主函数后,赋值表达式x=fsqr1(5.5)把临时变量的值赋给x,无名临时变量的生命期结束。
fsqr2没有临时变量的过渡,而是直接返回temp本身赋值给y。不产生副本,效率提高了,但返回值不再是表达式。 - 返回值为引用的函数作为左值:
- 统计学生成绩,分数在 80 分以上的为 A 类,60 分以上 80 分以下的为 B 类,60 分以下的为 C 类
-
1 int& level(int grade ,int& typeA ,int& typeB ,int& typeC) 2 { 3 if(grade>=80) return typeA ; 4 else if(grade>=60) return typeB; 5 else return typeC; 6 } 7 8 void main( ) 9 { 10 int typeA=0,typeB=0,typeC=0,student=9 ; 11 int array[9]={90 , 75 , 83 , 66 , 58 , 40 , 80 , 85 , 71} ; 12 for (int i=0 ; i<student ; i++) 13 level(array[i], typeA, typeB, typeC)++ ; //返回值为引用的函数作为左值 14 cout<<"A类学生数:"<<typeA<<endl ; 15 cout<<"B类学生数:"<<typeB<<endl ; 16 cout<<"C类学生数:"<<typeC<<endl ; 17 }
三、 复制构造函数(拷贝构造函数)------------- 用于根据一个已存在的对象复制出一个新的该类对象,一般在函数中会将已经存在的对象的数据成员的值复制一份到新创建的对象中。
1. 复制构造函数的引入:
- 同一个类的对象在内存中有完全相同的结构,如果作为一个整体进行复制是完全可能的。这个复制过程只需要复制数据成员,因为函数成员是共用的(在内存中只有一份代码)。在建立对象时可以用同一个类的另一个对象来初始化该对象,这时所用到的构造函数成为复制构造函数。
- 若没有显示的写复制构造函数,系统会默认创建一个复制构造函数但当类中有指针成员时,由系统创建的该复制构造函数就会存在风险。具体请看下边深复制与浅复制。
2. 复制构造函数的参数必须采用引用
在 C++ 中按值传递一个参数时,会在函数中重新分配一块内存建立与参数同类型的变量或对象,再把参数的数据成员赋值给新的变量或对象。在建立这个对象时,编译器就会自动为这个对象调用复制构造函数。如果其参数是真实的对象而不是引用,则又会引入新的一轮调用复制构造函数,出现了无穷递归。
3. 复制构造函数被调用的时机:
- 当用一个类的对象去初始化该类的另一个对象(或引用)时系统自动调用拷贝构造函数拷贝赋值。
- 若函数的形参为类对象,调用函数时,实参赋值给形参,系统会自动调用复制构造函数
- 当函数的返回值是类对象时,系统自动调用复制构造函数
-
1 对于CGoods类,复制构造函数为: 2 CGoods(CGoods & cgd) 3 { 4 strcpy(Name,cgd.Name); 5 price=cgd.price; 6 amount=cgd.amount; 7 total_value=cgd.toyal_value; 8 } 9 10 11 CGoods Car1("夏利2000",30,98000.0) 12 //调用三个参数的复制构造函数 13 CGoods Car2=Car1;//调用复制构造函数 14 CGoods Car3(Car1); 15 //调用复制构造函数,Car1为实参 16 这三个对象的初始化结果完全一样
示例代码:
-
1 class A 2 { 3 public: 5 A(const A& a){ 6 data=a.data; 7 cout<<"拷贝构造函数调用\n"; 8 } 9 A& operator=(const A&a){ 10 data=a.data; 11 cout<<"调用赋值函数\n"; 12 return *this; 13 } 14 15 int data; 16 }; 17 18 void fun1(A a) 19 { 20 return ; 21 } 22 23 A fun2() 24 { 25 A a; 26 return a; 27 } 28 29 int _tmain(int argc, _TCHAR* argv[]) 30 { 31 A a; 32 A b(a); //用类的一个对象a去初始化另一个对象b 33 A c=a; //用类的一个对象a去初始化另一个对象c,注意这里是初始化,不是赋值 34 fun1(a); //形参为类对象,实参初始化形参,调用拷贝构造函数。 35 A d=fun2(); //函数返回一个类对象时 36 d=a; //d已经初始化过了,这里是赋值,调用赋值函数 37 38 return 0; 39 } 40 //A c=a; d=a;前一个是初始化,后一个是赋值,两者不同
-
四、深复制与浅复制
当对一个对象进行拷贝时,编译系统会自动调用一种构造函数 -- 复制(拷贝)构造函数,如果用户未定义拷贝构造函数则会调用系统默认的拷贝构造函数。
- 在未自定义拷贝构造函数时,在复制对象时调用默认的拷贝构造函数时,进行的时浅拷贝。容易发生内存泄漏
- 深拷贝即调用的自定义的拷贝构造函数,不但对指针进行拷贝,还对指针指向的内容进行拷贝,拷贝后的指针是指向两个不同地址的指针。
1. 对类对象进行复制的时候即把对象各数据成员的值原样复制到目标对象中时。当类中涉及到指针类型的数据成员的时候,往往会产生指针悬挂问题。看个简单地例子:
-
1 class A 2 { 3 public: 4 int *a; 5 } 6 A a1; 7 A b1=a1;
b1=a1; 执行的是浅复制,此时 b1.a 与 a1.a 指向的是同一个内存地址,如果在析构函数里有对内存的释放就会出现内存访问异常。因为一块内存空间被释放了两次。
2. 看一个例子:有一个学生类,数据成员为学生的人数和名字
-
1 #include <iostream> 2 using namespace std; 3 4 class Student 5 { 6 private: 7 8 int num; 9 char *name; 10 public: 11 Student(); 12 ~Student(); 13 }; 14 15 Student::Student() 16 { 17 18 name=new char(20); 19 cout<<"Student"<<endl; 20 } 21 22 Studet::~Student() 23 { 24 cout<<"~Student"<<endl; 25 delete name; 26 name=NULL; 27 } 28 29 int main() 30 { 31 {//花括号让s1,s2变成局部对象,方便测试 32 Student s1; 33 Student s2(s1);//复制对象 34 sysem("ause"); 35 return 0; 36 } 37 }
- 执行结果是:调用一次构造函数一次复制构造函数调用两次析构函数。两个对象的指针成员所指向的内存相同。name 指针被分配一次内存,但是在程序结束时却被释放了两次,出现错误。
3. 所以在对含有指针成员的对象进行拷贝时,必须要自定义拷贝构造函数使拷贝后的对象指针成员有自己的内存空间,即进行深拷贝,这样就避免了内存泄漏的发生。
- 下边是添加了自定义拷贝函数的例子:
-
1 #include <iostream> 2 using namespace std; 3 4 class Student 5 { 6 private: 7 int num; 8 char *name; 9 public: 10 Student(); 11 ~Student(); 12 Student(const Student &s);//拷贝构造函数,const防止对象被改变 13 }; 14 15 Student::Student() 16 { 17 name = new char(20); 18 cout << "Student" << endl; 19 20 } 21 Student::~Student() 22 { 23 cout << "~Student " << (int)name << endl; 24 delete name; 25 name = NULL; 26 } 27 Student::Student(const Student &s) 28 { 29 name = new char(20); 30 memcpy(name, s.name, strlen(s.name)); 31 cout << "copy Student" << endl; 32 } 33 34 int main() 35 { 36 {// 花括号让s1和s2变成局部对象,方便测试 37 Student s1; 38 Student s2(s1);// 复制对象 39 } 40 system("pause"); 41 return 0; 42 }
- 执行过程:调用一次构造函数,一次自定义复制构造函数,两次析构函数。两个对象的指针成员所指内存不同
- 浅拷贝只是对指针的拷贝,拷贝后两个指针指向同一个内存空间。
- 深拷贝不仅对指针进行拷贝还对指针指向的内容进行拷贝,经过深拷贝后的指针是指向两个不同地址的指针。
-
要考虑自定义拷贝构造函数的情况有以下三种- 复制含指针成员的对象时即用一个类的对象去初始化该类的另一个对象的时候
- 函数的形参为类对象时。调用函数时会有实参到形参的拷贝此时会调用拷贝构造函数
- 当函数的返回为类对象时。在函数和返回时会建立一个和类对象一样的临时类对象变量,并将返回的类对象赋值给新创建的类对象,此时会调用拷贝构造函数
浅拷贝问题的本质在于析构函数释放多次堆内存,使用 std::shared_ptr 智能指针,可以完美解决这个问题
我们今天的关于PHP从构造函数获取返回值和php中构造函数的分享就到这里,谢谢您的阅读,如果想了解更多关于c – 复制构造函数与返回值优化、C#异步执行带有返回值和参数的方法,且获取返回值、C#构造函数、私有构造函数、静态构造函数与构造函数执行顺序、C++ 基础知识(八)--- 函数返回值(返回值,返回指针,返回对象,返回引用)--- 引用 --- 复制构造函数(拷贝构造函数)--- 深复制与浅复制的相关信息,可以在本站进行搜索。
本文标签: