VC用了N久敲代码无数.....今天给一新手调代码, 无意中发现......
class MyTest{};int main(){ //新手最易犯的毛病之1
MyTest mytest();//此乃函数声明, 非对象定义!
//正确的方法是
//MyTest mytest;
return 0;
}
这倒没啥, 问题是他拿着下面的代码回来问我.
class MyTest{};int main()
{ MyTest mytest(MyTest());
return 0;
}如果是个函数声明, mytest的原形为MyTest mytest(MyTest), 参数表里的括号是干啥的?
如果是个函数调用, 开头的MyTest是干啥的?
所以两种可能都不对, 代码是错误的. 用VS2008编译一下竟然通过了, 不过有个warning:
warning C4930: “MyTest mytest(MyTest (__cdecl *)(void))”: prototyped function not called (was a variable definition intended?)
查找CSDN, 原来VC把MyTest()解释为一个函数指针囧....
mytest就是个函数, 原形相当于MyTest mytest(MyTest (*pfun)(void));//注意下面的MyTest一个是类, 一个是函数, 重名的...class MyTest{
public:
MyTest(){ printf("construct of class MyTest\n"); }
};//MyTest的类型为void (*)(void), 因为是匿名的所以无法调用...
MyTest mytest(MyTest()){ printf("function: mytest\n");
//定义一个MyTest对象返回.
return MyTest();
}//这个函数当作mytest参数...
MyTest MyTest(void){ printf("function: MyTest\n");
//这是啥? 不是定义对象哦, 乃无限递归也!
return MyTest();
}int main()
{
//调用mytest...
mytest(MyTest);
//你想定义一个MyTest吗?
MyTest mt; //产生错误, 因为函数与类名相同.....
class MyTest mt//这样才正确.....
return 0;
}ps 显然如果类名和函数名相同, VC会用函数名覆盖类名, ISO C++里也是这么规定的吗?????
class MyTest{};int main(){ //新手最易犯的毛病之1
MyTest mytest();//此乃函数声明, 非对象定义!
//正确的方法是
//MyTest mytest;
return 0;
}
这倒没啥, 问题是他拿着下面的代码回来问我.
class MyTest{};int main()
{ MyTest mytest(MyTest());
return 0;
}如果是个函数声明, mytest的原形为MyTest mytest(MyTest), 参数表里的括号是干啥的?
如果是个函数调用, 开头的MyTest是干啥的?
所以两种可能都不对, 代码是错误的. 用VS2008编译一下竟然通过了, 不过有个warning:
warning C4930: “MyTest mytest(MyTest (__cdecl *)(void))”: prototyped function not called (was a variable definition intended?)
查找CSDN, 原来VC把MyTest()解释为一个函数指针囧....
mytest就是个函数, 原形相当于MyTest mytest(MyTest (*pfun)(void));//注意下面的MyTest一个是类, 一个是函数, 重名的...class MyTest{
public:
MyTest(){ printf("construct of class MyTest\n"); }
};//MyTest的类型为void (*)(void), 因为是匿名的所以无法调用...
MyTest mytest(MyTest()){ printf("function: mytest\n");
//定义一个MyTest对象返回.
return MyTest();
}//这个函数当作mytest参数...
MyTest MyTest(void){ printf("function: MyTest\n");
//这是啥? 不是定义对象哦, 乃无限递归也!
return MyTest();
}int main()
{
//调用mytest...
mytest(MyTest);
//你想定义一个MyTest吗?
MyTest mt; //产生错误, 因为函数与类名相同.....
class MyTest mt//这样才正确.....
return 0;
}ps 显然如果类名和函数名相同, VC会用函数名覆盖类名, ISO C++里也是这么规定的吗?????
class MyTest{};
int main(){
MyTest mytest(MyTest());
return 0;}
很正常,先调用构造,建一个MyTest()作为参数,再调用复制构造,把参数MyTest()传给mytest.但是我用VS2008,同样的代码,正如楼主那样,报警告,函数原型没被调用(你是想定义一个变量吗?)
但是我如何才可以告诉编译器,这是一个对象的定义,而非函数的声明呢?
VS2008里面,MyTest mytest(MyTest()){} MyTest()当作是 MyTest (*)()我在VC6里写MyTest mytest(MyTest()){} 会报错,function-style initializer appears to be a function definition
在VC6里,显式地写成MyTest mytest(MyTest (*)()) {} 这样才行.
结果跟楼主在VS2008一样,认为参数是一个函数指针,该指针的返回值是MyTest,参数表空.到底C++ 定义函数指针的写法是怎样的呢?VC6与VS2008有不同的标准?VS2008允许简化一些?
不过ISO C++太厚了我真有点懒的翻...
public:
MyTest(){
printf("MyTest Ctor\n");
}
MyTest(const MyTest& rhs){
printf("MyTest Copy Ctor\n");
*this = rhs;
}
};
int main(int argc, char* argv[])
{
MyTest mytest(MyTest()); getchar();
return 0;
}
这种写法,只有VC6是当作定义对象并执行复制构造.
VS2008,DevCpp都当作是一个函数的声明,并且参数是 MyTest (*)(void)
我跟楼主一样,对C++越来越孤陋寡闻了.
class MyTest{
public:
MyTest(){
printf("MyTest Ctor\n");
}
MyTest(const MyTest& rhs){
printf("MyTest Copy Ctor\n");
*this = rhs;
}
MyTest(int a){
printf("Ctor With Int\n");
}
void Func(){
printf("Func\n");
}
};
int _tmain(int argc, _TCHAR* argv[])
{
MyTest temp(1);
MyTest mytest(temp);
MyTest mytest1(MyTest(1)); getchar();
return 0;
}
加了一个带参的构造,编译器终于认为这是对象的定义,而非函数的声明了,但还是有诡异的事情.
MyTest temp(1); 上面2句应该等价于下面一句.
MyTest mytest(temp);
MyTest mytest1(MyTest(1));
但实际并不是这样,在VC6,上面2句的确等价于下面一句,先执行带参构造,再执行复制构造.
但在VS2008与DevCpp里面,结果一样,都是只执行了带参构造,没有执行复制构造.
查看一下汇编的代码.
MyTest mytest1(MyTest(10)); 这2行C代码,对应的汇编是这样的.
MyTest mytest2(10);
大家的汇编一样.
MyTest mytest1(MyTest(10));
00413694 push 0Ah
00413696 lea ecx,[mytest1]
00413699 call MyTest::MyTest (4111D1h)
MyTest mytest2(10);
0041369E push 0Ah
004136A0 lea ecx,[mytest2]
004136A3 call MyTest::MyTest (4111D1h) 而VC6的汇编是下面这样的.
28: MyTest mytest(MyTest(1));
00401278 push 1
0040127A lea ecx,[ebp-8]
0040127D call @ILT+20(MyTest::MyTest) (00401019)
00401282 push eax
00401283 lea ecx,[ebp-4]
00401286 call @ILT+0(MyTest::MyTest) (00401005)
看来是VS2008对代码有自己的优化,所以产生了与VC6不同的结果.
万一我在构造跟复制构造里搞了些什么东西,编译器给出的响应又不一样,有些编译器执行了复制构造,有些又没执行,release 与 debug 说不定也会出不同的优化.
我现在是越来越头晕了.
MyTest mytest1(MyTest(1));
MyTest(1)是个临时对象除了拷贝别无它用, 公然的浪费...
象样点的编译器都会跳过拷贝构造函数直接调用相应的构造函数,
但当参数为非临时对象时就会调用拷贝构造函数了. 此乃NRVO优化是也.
不过NRVO在一些情况下没办法进行优化, 所以C++0x隆重推出右值引用就是解决类似问题的.
#include <iostream>
using namespace std;class MyClass{public:
MyClass(){ cout << "Default constructor" << endl; }
MyClass(const MyClass&){ cout << "Copy constructor" << endl; }
MyClass(int){ cout << "Constructor with a int parameter" << endl; }};int main(){ MyClass m1; // default constructor
MyClass m2 = m1; // same as below
MyClass m3(m2); // copy constructor
//
MyClass m4(1); // call MyClass(int) by NRVO return 0;
}
#include <iostream>
using namespace std;class MyClass{public:
MyClass(){ cout << "Default constructor" << endl; }
MyClass(const MyClass&){ cout << "Copy constructor" << endl; }
MyClass(int){ cout << "Constructor with a int parameter" << endl; }};int main(){ MyClass m1; // default constructor
MyClass m2 = m1; // same as below
MyClass m3(m2); // copy constructor
MyClass m4(MyClass(1)); // MyClass(int) by NRVO return 0;
}
福利的同时,也有其副作用,导致了不一致的程序行为.楼主高人,加个QQ,以后多联系了.QQ 644832501
因此C++是令人丧气的,学得越多越感觉自己对很多东西其实是模糊的.
----事实上C++标准委员会的成员之间也有分歧,以致C++0x一直无法完成.
个人看法是:使用自己熟悉的C++特性来完成自己的工作.
这时就要小心了,呵呵.
不过这种需求很小, 拷贝构造函数还是尽量完成单纯的拷贝动作吧, 或者使用非临时变量强制调用拷贝构造函数.
总体来说利大于弊吧. 期待C++0x的右值引用.
高人不敢, 互相交流吧. 暂时上不了Q上了加你~~~~~~`