2012-09-16 130 views
0

我不明白这段代码是如何编译的。有人可以解释那里发生了什么。C++:为什么代码正在编译

#include <iostream> 

using namespace std; 

class B 
{ 
public:  
    B(const char* str = "\0") //default constructor 
    { 
     cout << "Constructor called" << endl; 
    }  

    B(const B &b) //copy constructor 
    { 
     cout << "Copy constructor called" << endl; 
    } 
}; 

int main() 
{ 
    B ob = "copy me"; //why no compilation error. 
    return 0; 
} 

的optput是: 构造称为

P.S:我想不出更恰当的标题比这个的,任何人谁能够想到一个更好的标题,请修改它。

+1

你为什么认为它不应该编译? –

+0

指定的行与数据类型不匹配 –

回答

10

"copy me"的类型是char const[8],其衰减到char const *。由于默认构造函数不是explicit,"copy me"可以隐式转换为B,因此ob可以从隐式转换的临时对象B复制构建。

有默认的构造函数被宣布explicit,你将不得不写下列之一:

B ob1 = B("copy me"); 
B ob2("copy me"); 

有拷贝构造函数被宣布explicit,你就不得不说其中之一:

B ob3(B("copy me")); 
B ob4("copy me"); 

在实践中,所有副本会被任何半体面的编译器被省略,而你总是有一个默认的构造函数调用结束。

3

[它不应该编译,因为]指定的行中不数据类型匹配

没有编译错误,因为那里存在需要const char*作为参数,允许的B构造在const char*B之间转换。

7

因为这

B ob = "copy me"; 

调用拷贝构造函数,这需要论证const B &b你类B有一个构造

B(const char* str = "\0") 

这是定义为explicit

允许编译器进行一次隐式转换。


那么,是什么在这里发生:

B ob = "copy me"; 

是:

  1. 创建一个临时的,未命名的对象B,使用提供const char* str - 这是允许的,因为class B有构造,它采用一个参数并且没有被定义为explicit。换句话说,所有类型为B的对象都可以构建于const char*
  2. 使用在1.中创建的临时对象创建对象ob
4

这是因为,以

B ob("copy me"); 

赋值语句的隐式转换试试这个失败编译(看explicit关键字):

#include <iostream> 

using namespace std; 

class B 
{ 
public:  
    explicit B(const char* str = "\0") //default constructor 
    { 
     cout << "Constructor called" << endl; 
    }  

    B(const B &b) //copy constructor 
    { 
     cout << "Copy constructor called" << endl; 
    } 
}; 

int main() 
{ 
    B ob = "copy me"; //why no compilation error. 
    return 0; 
} 
7

如果添加关键字明确到您的默认构造函数以防止隐式转换。然后它不会编译。你的答案是隐式转换。

0

这是因为隐式转换。添加一个Explicit到你的默认构造函数并尝试。它将无法编译。

-1

编辑:在与Kerrek SB讨论后,我得到了C++ 11标准的副本。我错了,这是暂时的。我正在编辑此回复以反映我最近获得的理解。我非常熟悉C++(大约在第一个标准发布的时候)。自1998年年底以来我没​​有使用它,所以我已经忘记了很多,我几乎不了解最近的标准。

该代码是正确的。

B ob = "copy me"; //why no compilation error. 

没有错误。这被解析为初始化变量的声明。 B是类型,ob变量的名称,"copy me"初始值设定项。

初始值设定项的类型为const char*,在B类中有一个构造函数,它带有一个const char*类型的单个参数。该构造函数未被explicit声明为限制,因此可以在此上下文中使用。

要么创建一个临时对象,然后复制(您可以看到两行都打印出来),或者复制被省略,只调用转换构造函数直接在目的地构造(您只能看到一行打印)。即使拷贝构造函数有副作用,标准也明确地允许这样做。

程序执行将打印构造函数调用标准输出为。它可能会也可能不会打印复制构造函数调用。没有错误。

+1

'B ob =“copy me”;'是** not **与'B ob(“copy me”);'相同。第一个是复制初始化,_formally_。 'Constru' called'可能被打印出来,因为编译器可能并且很可能会优化这个,通过删除不必要的副本并直接使用初始化来代替。无论如何,我没有投票,但你错了。 –

+1

由于在这一点上它们都是相同的,因此您正在阅读标准错误,无论是旧的还是新的。 –

+0

@KirilKirov我花了一些时间阅读标准(事实上有一些章节涉及)。你是对的。我相应地修改了我的答案。 –