仅学习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开始:绑定到构造函数初始化器列表中引用成员的临时项仅在构造函数退出之前一直存在,而不管对象是否存在。 (注意:从DR 1696开始,这种初始化是错误的)。 (直到C ++ 14)
这是gtest版本/ c ++版本不匹配吗?我是否在正确的轨道上了解这一点?
答案 0 :(得分:1)
您引用的cppreference的“直到C ++ 14”部分并不表示从C ++ 17开始,临时函数的生存期不再在构造函数退出时结束, 恰恰相反: [class.base.init/8]现在声明
绑定到mem初始化程序中引用成员的临时表达式格式错误。
那是您甚至不允许将引用成员绑定到临时成员。 我很惊讶您的代码甚至可以编译,好像GCC在这里没有完全符合要求。