Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

uninitialized_fill_n 的模板偏特化疑问,MyTinySTL的行为与标准库不同 #146

Open
woruyu opened this issue Feb 20, 2024 · 3 comments

Comments

@woruyu
Copy link

woruyu commented Feb 20, 2024

调用链
1.mytinyStl vector(size_type n, const value_type& value) -> fill_init->mystl::uninitialized_fill_n(使用std::is_trivially_copy_assignable检查是否具有平凡的拷贝赋值运算符)->false 构造函数初始化,true 编译器自动生成的赋值运算符初始化
2.实际的c++标准库(ubuntu /usr/include/c++/12/bits/stl_vector.h) vector(size_type __n, const value_type& __value,...)->_M_fill_initialize -> std::__uninitialized_fill_n_a -> std::uninitialized_fill_n(__can_fill = is_copy_assignable<_ValueType>,这里只检查了是否有可用的拷贝赋值运算符,__is_trivial(_ValueType) 这个class是平凡的吗 ) -> ture, 值拷贝就是使用编译器自动生成的赋值运算符初始化, false 构造函数初始化。

逻辑:
__is_trivial && is_copy_assignable 是否等价于 std::is_trivially_copy_assignable,答案是否定的__is_trivial很严格,需要有平凡的默认构造函数、拷贝构造函数、移动构造函数、拷贝赋值运算符、移动赋值运算符和析构函数(全是编译器自己生成的)。此外,它不能包含虚函数或虚基类,也不能有非平凡的非静态数据成员数,is_copy_assignable 只检查是否有可用的拷贝赋值运算符,而std::is_trivially_copy_assignable只检查是否具有平凡的拷贝赋值运算符,也就是拷贝赋值运算符必须是编译器自己生成的,而且class里面不包含虚函数等等的。

code:
class A {
int a;
int c;
int *b;

public:
A() { std::cout << "consturctor A" << std::endl; };
A(const A &ra) { std::cout << "copy consturctor A" << std::endl; };
};

int main() {
A a{};
mystl::vector aa(10, a);
}

difference:
c++标准库会调用10次拷贝构造函数进行初始化, 而mytinySTL却调用10次值拷贝

@woruyu woruyu changed the title uninitialized_fill_n 的模板偏特化疑问 uninitialized_fill_n 的模板偏特化疑问,MyTinySTL的行为与标准库不同 Feb 20, 2024
@frederick-vs-ja
Copy link
Contributor

uninitialized_fill_n 不应该检查 is_trivially_copy_assignable。这个函数应该只构造范围中的元素对象,而不应该对元素赋值。

@woruyu
Copy link
Author

woruyu commented Mar 28, 2024

uninitialized_fill_n 不应该检查 is_trivially_copy_assignable。这个函数应该只构造范围中的元素对象,而不应该对元素赋值。

如果不检查is_trivially,怎么优化trivial的class,只进行值拷贝,而不是一直调用构造函数呢?

@frederick-vs-ja
Copy link
Contributor

uninitialized_fill_n 不应该检查 is_trivially_copy_assignable。这个函数应该只构造范围中的元素对象,而不应该对元素赋值。

如果不检查is_trivially,怎么优化trivial的class,只进行值拷贝,而不是一直调用构造函数呢?

应该检查 is_trivially_copy_constructible

另外编译器应该也能自己优化?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants