c++ - 当返回一个用花括号初始化列表初始化的对象时,我能保证一对构造函数和析构函数调用吗?

标签 c++ c++11

以下面的类为例

#include <iostream>

using namespace std;

class A{
private:
    int a_;
    int b_;

    A(const A&) = delete;
    A& operator=(const A&) = delete;
    A(A&&) = delete;
    A& operator=(A&&) = delete;

public:
    A(int a, int b) : a_{a}, b_{b}{cout<<"constructed\n";}

    void ephemeral() const{cout<<"operation\n";}

    ~A(){cout<<"destructed\n";}

};

A make_A(int a, int b){
    return {a, b};
}

int main(){
    make_A(1, 2).ephemeral();
    return 0;
}

It gives the expected result .

构造对象,执行操作,然后销毁。

但是,我担心这是否得到保证。我主要担心的是,由于标准赋予编译器的自由,我是否会看到我不知道的任何效果。

我不认为复制省略是这里的一个因素,因为所有移动和复制构造函数都被声明为已删除,所以如何调用它们?

唯一被调用的构造函数是接受两个整数的构造函数。我能确定这将在编译器、平台和优化级别上保持一致吗?

我怀疑答案是"is",但可能会有一些微妙之处。

最佳答案

当你return {a,b};你直接构造返回值。

没有创建临时的、逻辑的或其他的。没有省略。

此返回值在 main 的返回上下文中可用.你可以调用它的.ephemeral()手术。在完整表达式的末尾,它超出范围,除非您将它“存储”在 A const& 中。 (引用生命周期延长开始)或 A&& (同上)或在 auto const& 中或 auto&&像这样的变量:

auto&& a = make_A(1, 2);
a.ephemeral();

仍然,在上述情况下,没有发生复制。

这些操作都不会导致标准下的复制。

在某些情况下,您是正确的,复制构造可以被删除。省略是指两个对象的身份和生命周期合并。所以如果make_A阅读:

A make_A(int a, int b){
  A r{a,b};
  return r;
}

r可以省略到返回值中。然而,在这里,编译器会要求 A(A const&)A(A&&)被定义,所以它不会用你的 A 编译.实际上,一旦检查到它们已定义,它就不会调用它们,因为 rmake_A 内将被忽略为与 make_A 的返回值相同的对象.

同样,

A a = make_A(1,2);

make_A 返回的临时文件省略为与命名变量相同 a .省略是暂时的,所以这也可以一起省略变量within make_A .在这种情况下,您还需要 A(A&&)A(A const&)存在。

通过删除移动/复制构造器,它们无法被调用,因此对象无法被复制。每个构造函数只能调用一个析构函数(除非手动构造或销毁)。

如果代码尝试调用它们,将在编译时产生错误。


在 C++17 中你甚至可以 return A(a,b);并发生类似的保证。

您也可以A a = make_A(1,2);并发生类似的保证。

这被描述为“保证省略”,而是将一些操作变成了“如何构造某些东西的描述”。

因此,在某些情况下,您可以在 C++03 或 C++11 或 C++14 中执行需要移动或复制 ctors 的操作,但在 C++17 中现在执行类似于“elision”的操作"并且不再需要移动或复制 ctors。

关于c++ - 当返回一个用花括号初始化列表初始化的对象时,我能保证一对构造函数和析构函数调用吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39880720/

相关文章:

C++获取文件扩展名而不在路径中提供扩展名

c++ - 接口(interface)和实现问题?

在另一个类中使用抽象类对象的 C++ 设计模式

c++ - C++ 程序员关于 Scala 的问题(结构和 STL)

c++ - 如何在C++上启动异步线程

c++ - 将 C++ 应用程序分发为 .exe 或 .msi?

c++ - 编译时循环遍历模板化类型

c++ - std::thread 线程在对象中分离出来,它什么时候终止?

c++ - 根据模板参数声明成员或不声明成员

C++ std::function 返回它自己类型的 vector (再次递归类型)