在std::bitset::operator[]中创建的std::bitset::reference对象的生存期? 我一直在看标准C++库头的头文件。我发现重载运算符[]运算符[](size\t ndx)(在类位集中定义)返回类引用的temproray对象 reference operator[](size_t __position) { return reference(*this,__position); }

在std::bitset::operator[]中创建的std::bitset::reference对象的生存期? 我一直在看标准C++库头的头文件。我发现重载运算符[]运算符[](size\t ndx)(在类位集中定义)返回类引用的temproray对象 reference operator[](size_t __position) { return reference(*this,__position); },c++,bitset,C++,Bitset,这个重载运算符封装了单个位的概念。此类的实例是实际位的代理。它在以下表达式中很有用: bitset<10> b; b[2] = true; 然而,我对这个表达感到困惑: if (b[2]) { //Do something } b[2]首先返回类reference的临时对象,然后对返回的临时对象调用重载运算符(operator bool()const),将其转换为bool数据类型 // For __x = b[i]; operator bool() const { ret

这个重载运算符封装了单个位的概念。此类的实例是实际位的代理。它在以下表达式中很有用:

bitset<10> b;
b[2] = true;
然而,我对这个表达感到困惑:

if (b[2]) {
    //Do something
}
b[2]
首先返回类
reference
的临时对象,然后对返回的临时对象调用重载运算符(
operator bool()const
),将其转换为
bool
数据类型

// For __x = b[i];
operator bool() const
{ return (*(_M_wp) & _Base::_S_maskbit(_M_bpos)) != 0; }
如果临时对象(具有自动存储类的对象)是在堆栈上创建的,那么调用另一个函数(
操作符bool()const
)不应该破坏第一个函数调用返回的临时对象(
引用
引用操作符[](大小t位置))返回的对象)

在C和C++中临时对象的生存期是什么?

< P> >代码中的条件>(b(2))< /> >包含<代码>操作符布尔()/> >是一个表达式,临时函数对于表达式的整个生命周期是有效的。

,强调的是我的。< /P> 当实现引入具有非平凡构造函数([class.ctor]、[class.copy])的类的临时对象时,它应确保为临时对象调用构造函数。类似地,应使用非平凡析构函数([class.dtor])调用析构函数进行临时调用临时对象作为计算完整表达式([intro.execution])的最后一步被销毁,该表达式(词汇上)包含创建临时对象的点。即使该计算以引发异常结束,也是如此。销毁临时对象的值计算和副作用仅与完整表达式关联,而不与任何特定的子表达式关联

该临时对象将在给定表达式的最后一步被销毁

事实上,C++依赖于它,因为这个非常常见的表达式可以正确工作:

int x = 0, y = 0, z = 0, t = 0;
int a = x + y + z + t;
因为
x+y
是临时的,
x+y+z
是另一个临时的


临时文件的使用寿命将按照中的规则缩短

有三种情况下,临时性词语在不同于完整表达结束时被销毁。第一个上下文是当调用默认构造函数来初始化没有相应初始值设定项([dcl.init])的数组元素时。第二个上下文是在复制整个数组([expr.prim.lambda]、[class.copy])时调用复制构造函数来复制数组的元素。在这两种情况下,如果构造函数有一个或多个默认参数,则在构造下一个数组元素(如果有)之前,将按顺序销毁在默认参数中创建的每个临时变量

并将按照以下规则延长:

第三个上下文是引用绑定到临时对象时。116引用绑定到的临时对象或作为引用绑定到的子对象的完整对象的临时对象在引用的生命周期内持续存在,但以下情况除外:

  • 在函数调用([expr.call])中绑定到引用参数的临时对象将一直存在,直到包含该调用的完整表达式完成

  • 函数返回语句([stmt.return])中返回值的临时绑定的生存期未延长;在return语句的完整表达式末尾销毁临时表达式

  • 与新初始值设定项([expr.new])中的引用的临时绑定将持续存在,直到包含新初始值设定项的完整表达式完成

在本例中可以看到第一个上下文:

struct bar {
    bar() { std::cout << __func__ << '\n'; }
    bar(const bar&) { std::cout << __func__ << "__\n"; }
    ~bar() { std::cout << __func__ << '\n'; }
};

struct foo {
    foo(const bar& b = bar()) { std::cout << __func__ << '\n'; }
};

int main() {
    foo f[] = {foo(), foo()};
}
第二个上下文将添加到C++17中,从此程序开始:

struct bar {
    bar() { std::cout << __func__ << '\n'; }
    bar(const bar&) { std::cout << __func__ << "__\n"; }
    ~bar() { std::cout << __func__ << '\n'; }
};

struct foo {
    foo() {}
    foo(const foo&, const bar& b = bar()) { std::cout << __func__ << "__\n"; }
};

struct foox {
    foo f[2];
};

int main() {
    foox fx;
    foox yx = fx;
}

对于第三个上下文,您可以在中找到答案,

您的答案有一个例外-一个临时变量可以绑定到一个命名的常量引用变量,并且它的生存期延长到所述变量的生存期。@Leon实际上,有三个上下文的生存期不同,我加上去的here@Danh你能详细说明更多的类。临时5和类。临时6吗?@abhiarora根据你的需要更新
bar
foo
~bar
bar
foo
~bar
struct bar {
    bar() { std::cout << __func__ << '\n'; }
    bar(const bar&) { std::cout << __func__ << "__\n"; }
    ~bar() { std::cout << __func__ << '\n'; }
};

struct foo {
    foo() {}
    foo(const foo&, const bar& b = bar()) { std::cout << __func__ << "__\n"; }
};

struct foox {
    foo f[2];
};

int main() {
    foox fx;
    foox yx = fx;
}
bar
foo__
~bar
bar
foo__
~bar