Naw*_*waz 8 c++ initialization copy-constructor copy-initialization
我正在阅读直接初始化和复制初始化(§8.5/ 12)之间的区别:
T x(a);  //direct-initialization
T y = a; //copy-initialization
我从阅读有关复制初始化的内容中了解到,它需要可访问和非显式的复制构造函数,否则程序将无法编译.我通过编写以下代码验证了它:
struct A
{
   int i;
       A(int i) : i(i) { std::cout << " A(int i)" << std::endl; }
   private:
       A(const A &a)  {  std::cout << " A(const A &)" << std::endl; }
};
int main() {
        A a = 10; //error - copy-ctor is private!
}
GCC给出了一个错误(ideone)说:
prog.cpp:8:错误:'A :: A(const A&)'是私有的
到目前为止,一切都很好,重申Herb Sutter所说的,
复制初始化意味着在必要时首次调用用户定义的转换后,使用复制构造函数初始化对象,并且等效于"T t = u;"形式:
之后,我通过评论private关键字来访问copy-ctor .现在,我自然希望以下内容得到印刷:
A(const A&)
但令我惊讶的是,它打印出来(ideone):
A(int i)
为什么?
好的,我明白第一类型的临时对象A被创建出来的10,其是int类型,通过使用A(int i),应用转换规则作为其在这里需要(第8.5节/ 14),然后它应该调用复制构造函数来初始化a.但事实并非如此.为什么?
如果允许实现消除调用copy-constructor(第8.5/14节)的需要,那么为什么在声明copy-constructor时它不接受代码private?毕竟,它没有称之为.它像一个被宠坏的孩子谁第一个恼人要求一个特定的玩具,当你给他一个,在特定的一个,他投出去了,你的背后.:|
这种行为会有危险吗?我的意思是,我可能会在copy-ctor中做一些其他有用的事情,但是如果它没有调用它,那么它是否会改变程序的行为?
Ste*_*sop 10
你在问为什么编译器会进行访问检查吗?12.8/14 in C++ 03:
如果隐式使用对象的复制构造函数或复制赋值运算符并且无法访问特殊成员函数,则程序格式错误
当实现"省略复制结构"(由12.8/15允许)时,我不认为这意味着复制文件不再"隐式使用",它只是不执行.
或者你在问为什么标准会这么说?如果复制省略是关于访问检查的此规则的一个例外,那么您的程序将在成功执行省略的实现中形成良好的形式,但在实现不成功的实现中则是错误的.
我很确定作者会认为这是一件坏事.当然,以这种方式编写可移植代码更容易 - 编译器会告诉您是否编写了试图复制不可复制对象的代码,即使副本恰好在您的实现中被删除.我怀疑实施者在检查访问权限之前确定优化是否成功(或者在尝试优化之后推迟访问检查)也会给实施者带来不便,尽管我不知道这是否值得考虑.
这种行为会有危险吗?我的意思是,我可能会在copy-ctor中做一些其他有用的事情,但是如果它没有调用它,那么它是否会改变程序的行为?
当然它可能很危险 - 当且仅当对象被实际复制时才会出现副本构造函数中的副作用,并且您应该相应地设计它们:标准说副本可以省略,所以不要将代码放在复制构造函数中,除非你很高兴在12.8/15中定义的条件下被淘汰:
MyObject(const MyObject &other) {
    std::cout << "copy " << (void*)(&other) << " to " << (void*)this << "\n"; // OK
    std::cout << "object returned from function\n"; // dangerous: if the copy is
      // elided then an object will be returned but you won't see the message.
}
C++显式允许几个涉及实际更改程序语义的复制构造函数的优化.(这与大多数优化形成对比,这些优化不会影响程序的语义).特别是,有几种情况允许编译器重新使用现有对象,而不是复制一个,如果它知道现有对象将无法访问.这种(复制结构)就是这样一种情况; 另一个类似的情况是"返回值优化"(RVO),如果你声明保存函数返回值的变量,那么C++可以选择在调用者的帧上分配它,这样它就不需要了在函数完成时将其复制回调用者.
一般来说,在C++中,如果你定义一个副作用或除了复制之外还做任何其他事情的复制构造函数,你就会玩火.
| 归档时间: | 
 | 
| 查看次数: | 717 次 | 
| 最近记录: |