0

我最近写了一段代码

SomeClass someObject;
mysqlpp::StoreQueryResult result = someObject.getResult();

其中 SomeClass::getResult() 看起来像:

mysqlpp::StoreQueryResult SomeClass::getResult()
{
mysqlpp::StoreQueryResult res = ...<something>...;
return res;
}

现在,使用第一个代码片段中的示例,当我编译并运行时,程序因 ABORT 信号而崩溃。然后我将第一个片段更改为:

SomeClass someObject;
mysqlpp::StoreQueryResult result(someObject.getResult());

效果很好。另外,为了尝试一下,我再次将其更改为:

SomeClass someObject;
mysqlpp::StoreQueryResult result;
result = someObject.getResult();

这也很好用。

现在,我只是想不通为什么第一个例子失败了,而接下来的两个成功了。据我了解,在第一个示例中,复制构造函数用于初始化结果。但是第二个例子不也是这样吗?那么为什么第二个例子成功了呢?第三个例子更有意义——因为没有使用复制 const,我们只是在构造之后赋值。

简而言之,有什么区别:

FooClass a = someObject.someMethodReturningFooClassInstance();

FooClass a(someObject.someMethodReturningFooClassInstance());?

多谢!

4

6 回答 6

4

我认为这两种情况没有任何区别。两次调用相同的复制构造函数。

您确定这正是您在代码中编写的内容吗?

于 2009-01-02T12:10:43.510 回答
2

严格来说,在第一种情况下调用默认构造函数,然后调用赋值运算符,在第二种情况下,它只使用复制构造函数。

好的,我最初的假设是错误的,显然在这两种情况下都只会调用复制构造函数(在赋值情况下,也可能会调用额外的“转换”构造函数)。我会在休眠后启动编译器并在我的开发环境中验证这一点。

于 2009-01-02T12:14:44.623 回答
1

您可以在复制构造函数中放置一个断点(甚至是一个 printf 语句),并且您会确切地知道它何时被调用,您知道的。所以不能代替基本调试。;)

但是,是的,应该在前两种情况下调用复制构造函数。第三种情况使用赋值运算符。

您是否尝试在调试器中运行它?它应该在 ABORT 信号上中断。

于 2009-01-02T12:13:59.837 回答
0

在最纯粹的理论中,在这两种情况下都应该调用复制构造函数。但是,在这些情况下允许编译器使用一种称为返回值优化 (RVO) 的东西。如果使用 RVO,则不会调用复制构造函数。也许您的编译器在一种情况下使用 RVO 而不是另一种情况?

编辑:这只适用于这种情况

SomeClass someObject;
mysqlpp::StoreQueryResult result;
result = someObject.getResult();
于 2009-01-02T12:15:42.203 回答
0

实际上,第一个将使用 operator= 进行中间复制,而第二个将进行直接复制构造。

于 2009-01-02T12:16:08.817 回答
0

我认为第一种情况是为对象分配值(正确的值)。它向对象发送值。在 2,3 示例中是隐式对象和显式对象概念。您不应该通过为直接对象分配值来编写代码。

于 2009-01-02T15:19:17.543 回答