【发布时间】:2020-07-19 00:37:11
【问题描述】:
最近,我将我的编译器从 gcc-4.3.x 更新到 gcc-7.x,然后我的一位测试人员遇到了 Assert 异常。
代码如下:
struct data {
data() : _c(0) { ++CREATED; std::cout<<"data CREATED +1"<<_c<<" addres: "<<&_c<<std::endl;}
data(char c) : _c(c) { ++CREATED; std::cout<<"data with C CREATED +1"<<_c<<std::endl;}
data(const data& rhs) : _c(rhs._c) { ++COPIED; }
~data() { ++DESTROYED; std::cout<<"data DESTROYED +1"<<_c<<std::endl;}
char _c;
static size_t CREATED;
static size_t COPIED;
static size_t DESTROYED;
};
size_t data::CREATED = 0;
size_t data::COPIED = 0;
size_t data::DESTROYED = 0;
void testStringReferenceCopiable() {
typedef std::basic_string<data> data_str;
std::cout<<"1"<<std::endl;
data d[] = {'a', 'b', 'c'};
std::cout<<"2"<<std::endl;
data_str s( &d[0], 3 );
std::cout<<"3"<<std::endl;
data_str s2 = s;
std::cout<<"4"<<std::endl;
data_str s3;
std::cout<<"5"<<std::endl;
s3 = s;
}
对于 gcc7.x 的输出如下:
1
data(char c) CREATED +1a
data(char c) CREATED +1b
data(char c) CREATED +1c
2
data() CREATED +1
~data() DESTROYED +1
3
data() CREATED +1
~data() DESTROYED +1
4
data() CREATED +1
~data() DESTROYED +1
5
data() CREATED +1
~data() DESTROYED +1
~data() DESTROYED +1c
~data() DESTROYED +1b
~data() DESTROYED +1a
对于gcc4.3.x版本,输出为:
data CREATED +1
1
data with C CREATED +1a
data with C CREATED +1b
data with C CREATED +1c
2
3
4
5
data DESTROYED +1c
data DESTROYED +1b
data DESTROYED +1a
data DESTROYED +1
基本上我可以理解为什么它每次都调用 Construct of data() ,可能是因为空终止符。但我不明白为什么它每次都调用数据的析构函数。谁能给我答案?
谢谢!
【问题讨论】:
-
您正在对 std::basic_string 的内部工作进行单元测试?这是一个明智的测试吗?
-
如果你不想让代码在对象死亡时运行,不要让它的析构函数变得不重要
-
从 gcc 9.这个代码甚至不会编译。
static_assert(is_trivial_v<_CharT> && is_standard_layout_v<_CharT>);失败。 -
这里很多地方的未定义行为。新版本的 gcc 将其标记为红旗只是时间问题。
-
添加空终止的实现,例如
buffer[length] = CharT{}可以解释这种行为,因为它创建了一个临时对象来复制。您应该查看标准库中basic_string的实际实现以获得具体答案。