c++ - 使用临时的 gtest fixture 引用类成员的初始化

标签 c++ c++17 googletest

刚刚学习 gtest,遇到了一些我不明白的关于对象生命周期的问题。鉴于此测试夹具使用临时初始化类成员引用:

#include "gtest/gtest.h"

struct Base {

  bool check() const {
    if (str_ == "test") return true;
    return false;
  }

  private:
    std::string str_{"test"}; 
};  

struct Foo : public Base {};

class FooTest : public ::testing::Test {
protected:
  FooTest() : b{Foo{}} {}
  const Base& b;
};

TEST_F(FooTest, RefOne) {
  const Base& x{Foo{}};
  ASSERT_TRUE(x.check());
}

TEST_F(FooTest, RefTwo) {
  ASSERT_TRUE(b.check());
}

第一个测试通过,第二个测试失败,引用未初始化。

但是如果我用我自己的测试类测试完全相同的 Base 和 Foo 代码并通过 main 访问 check() 方法:

// same Base and Foo code

struct Tester { 
  Tester() : b{Foo{}}

  const Base& get() const {
    return b;
  }

private:
  const Base& b;
};

int main() {
  Tester t;
  if (t.get().check()) std::cout << "Pass." << std::endl;
}

引用有效。我能让 gtest 版本通过的唯一方法是用左值初始化引用。

我正在使用 gtest 1.8.0 并使用 g++ -std=c++17 -g -Wall -O3 进行构建。

来自 cppreference:绑定(bind)到构造函数初始化列表中的引用成员的临时绑定(bind)仅持续到构造函数退出,而不是只要对象存在。 (注意:从 DR 1696 开始,这种初始化是错误的)。 (直到 C++14)

这是 gtest 版本/c++ 版本不匹配吗?我的理解是否正确?

最佳答案

您引用的 cppreference 的“直到 C++14”部分并不意味着从 C++17 开始,当构造函数退出时,临时对象的生命周期不再结束, 恰恰相反: [class.base.init/8]现在说

A temporary expression bound to a reference member in a mem-initializer is ill-formed.

也就是说,您不再被允许将引用成员绑定(bind)到临时成员。 我很惊讶你的代码甚至编译,似乎 GCC 在这里不完全符合。

关于c++ - 使用临时的 gtest fixture 引用类成员的初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52355813/

相关文章:

c++ - 修改嵌套lambda中捕获的参数 : gcc vs clang?

c++ - 当取消请求排队时,pthread_cancel() 将如何响应?

c++ - 模板模板参数的替换失败

c++ - 自 Visual Studio 15.6.2 编译器更新标准以来,新的 C++17 [[nodiscard]] 警告是否符合标准?

c++ - GMock : How to return a fuction pointer defined by an EXPECT_CALL()

c++ - 可以吗在 Google 测试框架内的 TDD 周期中使用全局数据进行多个测试?

java - 单元测试需要很多接口(interface)?

c++ - 访问类成员 C++

c++ - 如何将 decltype 与成员函数一起使用

c++ - 在运行时确定缓冲区的大小? (套接字编程)