复制初始化的奇怪行为,不会调用复制构造函数! [英] Strange behavior of copy-initialization, doesn't call the copy-constructor!

查看:159
本文介绍了复制初始化的奇怪行为,不会调用复制构造函数!的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读直接初始化和复制初始化之间的区别(第8.5 / 12节):

I was reading the difference between direct-initialization and copy-initialization (§8.5/12):

T x(a);  //direct-initialization
T y = a; //copy-initialization

我从阅读复制初始化中的差异在于它需要可访问的&非明确的复制构造器,否则程序将无法编译。我通过编写以下代码进行了验证:

What I understand from reading about copy-initialization is that it needs accessible & non-explicit copy-constructor, or else the program wouldn't compile. I verified it by writing the following code:

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 )说:

GCC gives an error (ideone) saying:


prog.cpp:8:错误:'A :: A(const A&)'是私有的

prog.cpp:8: error: ‘A::A(const A&)’ is private

到目前为止,一切都很好,重申Herb Sutter所说的话

So far everything is fine, reaffirming what Herb Sutter says,


复制初始化是指在必要时首先调用用户定义的转换后,使用复制构造函数初始化对象,其等效形式为 T t = u;:

Copy initialization means the object is initialized using the copy constructor, after first calling a user-defined conversion if necessary, and is equivalent to the form "T t = u;":






此后,我通过评论 private来使copy-ctor可用。 关键字。现在,我自然希望可以打印出以下内容:


After that I made the copy-ctor accessible by commenting the private keyword. Now, naturally I would expect the following to get printed:


A(const A&)

A(const A&)

但令我惊讶的是,它却打印了这个( ideone ):

But to my surprise, it prints this instead (ideone):


A(int i)

A(int i)

为什么?

好的,我知道首先创建一个 A 类型的临时对象 10 int 类型,通过使用 A(int i),根据需要在此处应用转换规则(第8.5 / 14节),然后应该调用copy-ctor初始化 a 。但事实并非如此。为什么?

Alright, I understand that first a temporary object of type A is created out of 10 which is int type, by using A(int i), applying the conversion rule as its needed here (§8.5/14), and then it was supposed to call copy-ctor to initialize a. But it didn't. Why?

如果允许实现消除对调用复制构造函数的需要(第8.5 / 14节),那么为什么在复制构造函数为true时它不接受代码声明为私人?毕竟,它没有调用它。它就像一个被宠坏的孩子,先是恼人地要求一个特定的玩具,当您给他一个特定的玩具时,他把它扔了,扔在了您的背后。 :|

If an implementation is permitted to eliminate the need to call copy-constructor (§8.5/14), then why is it not accepting the code when the copy-constructor is declared private? After all, its not calling it. Its like a spoiled kid who first irritatingly asks for a specific toy, and when you give him one, the specific one, he throws it away, behind your back. :|

这种行为危险吗?我的意思是,我可能会在copy-ctor中做一些其他的有用事情,但是如果不调用它,那么它不会改变程序的行为吗?

Could this behavior be dangerous? I mean, I might do some other useful thing in the copy-ctor, but if it doesn't call it, then does it not alter the behavior of the program?

推荐答案

您是否在问为什么编译器要进行访问检查?在C ++ 03中为12.8 / 14:

Are you asking why the compiler does the access check? 12.8/14 in C++03:


如果复制
构造函数或复制赋值$,则程序格式错误对象的b $ b运算符被隐式使用
并且特殊成员函数
无法访问

A program is ill-formed if the copy constructor or the copy assignment operator for an object is implicitly used and the special member function is not accessible

何时该实现省略了复制构造(15.2.8允许),我不认为这意味着不再隐式使用复制ctor,而只是不执行复制。

When the implementation "omits the copy construction" (permitted by 12.8/15), I don't believe this means that the copy ctor is no longer "implicitly used", it just isn't executed.

还是您在问标准为何这么说?如果复制省略是该访问检查规则的例外,则您的程序在成功执行省略的实现中会采用正确的格式,而在没有执行的实现中则采用不正确的格式。

Or are you asking why the standard says that? If copy elision were an exception to this rule about the access check, your program would be well-formed in implementations that successfully perform the elision, but ill-formed in implementations that don't.

我很确定作者会认为这是一件坏事。当然,以这种方式编写可移植代码会更容易-编译器会告诉您是否编写了试图来复制不可复制对象的代码,即使该复制碰巧在您的实现中被删除了。我怀疑这也可能给实现者带来不便,以便在检查访问之前 确定优化是否成功(或将访问检查推迟到尝试进行优化之后),尽管我不知道这样做是否必要考虑。

I'm pretty sure the authors would consider this a Bad Thing. Certainly it's easier to write portable code this way -- the compiler tells you if you write code that attempts to copy a non-copyable object, even if the copy happens to be elided in your implementation. I suspect that it could also inconvenience implementers to figure out whether the optimization will be successful before checking access (or to defer the access check until after the optimization is attempted), although I have no idea whether that warranted consideration.


这种行为危险吗?我
的意思是,我可能会在copy-ctor中做一些其他有用的
事情,但是如果
没有调用它,那么它不会改变
的行为程序?

Could this behavior be dangerous? I mean, I might do some other useful thing in the copy-ctor, but if it doesn't call it, then does it not alter the behavior of the program?

当然,这可能很危险-当且仅当对象被实际复制时,复制构造函数才会产生副作用。您应该相应地进行设计:标准规定可以删除副本,因此,除非您对在12.8 / 15中定义的条件被删除感到高兴,否则不要将代码放入副本构造函数中。

Of course it could be dangerous - side-effects in copy constructors occur if and only if the object is actually copied, and you should design them accordingly: the standard says copies can be elided, so don't put code in a copy constructor unless you're happy for it to be elided under the conditions defined in 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.
}

这篇关于复制初始化的奇怪行为,不会调用复制构造函数!的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆