By default vậy compile g++ có hay không có thì cũng như nhau nhỉ.try-catch bt là bt ntn? Đọc cho kỹ vào.
GCC enables it by default for languages like C++ that normally require exception handling, and disables it for languages like C that do not normally require it. However, you may need to enable this option when compiling C code that needs to interoperate properly with exception handlers written in C++.
By default vậy compile g++ có hay không có thì cũng như nhau nhỉ.
Với lại try catch không handle được segfault phải không thím ?
Giống như ông bribnt nói đó. segfault là signal. Muốn catch đc nó thì phải viết signal handler. Cái signal handler nó giới hạn nhiều thứ, k viết đc giống như function bt đâu, cẩn thận kẻo ăn hành.By default vậy compile g++ có hay không có thì cũng như nhau nhỉ.
Với lại try catch không handle được segfault phải không thím ?
mình đang mời ae vào làm cùng nhé, có gì ae giúp nhau. Chứ không phải nói trình mình cao nhéanh em nào cần kiếm chỗ để thi triển mấy tuyệt chiêu C++ trong topic thì inbox mình nhớ.
Cũng đang nghiên cứu C++ generic programming
Segfault nó crash mịa nó nguyên cái process luôn signal handler cái gì, bác hiểu câu hỏi không?Giống như ông bribnt nói đó. segfault là signal. Muốn catch đc nó thì phải viết signal handler. Cái signal handler nó giới hạn nhiều thứ, k viết đc giống như function bt đâu, cẩn thận kẻo ăn hành.
https://stackoverflow.com/questions/1717991/throwing-an-exception-from-within-a-signal-handler
Còn muốn ăn sẵn thì search lib mà xài
https://github.com/Plaristote/segvcatch
![]()
Cũng khác nhiều đó.
VD case này:
C++:#include <cstdio> struct A { int x; A() {} }; struct B { int x; B() = default; }; int main() { A a; printf("A = %d\n", a.x); A a2{}; printf("A2 = %d\n", a2.x); B b; printf("B = %d\n", b.x); B b2{}; printf("B2 = %d\n", b2.x); }
Thì chỉ có dòng cuối cùng mới đảm bảo ra bằng 0, còn lại là random. Vì chỉ có dòng đó mới thỏa mãn điều kiện để gọi zero-initialized.
https://en.cppreference.com/w/cpp/language/value_initialization
https://en.cppreference.com/w/cpp/language/default_initialization
Nếu build optimize thì hầu hết compiler sẽ tự zero-initialized, tuy nhiên cũng không nên quá dựa vào điều này.
// TB: test build local -O0 mới ra random, dùng mấy cái online nó có cơ chế gì đó nên ra 0 hết.
Theo ý hiểu của em thì doThe effects of default initialization are: (1)
- if T is a (possibly cv-qualified) non-POD (until C++11) class type, the constructors are considered and subjected to overload resolution against the empty argument list. The constructor selected (which is one of the default constructors) is called to provide the initial value for the new object;
- if T is an array type, every element of the array is default-initialized;
- otherwise, no initialization is performed (see notes).
int x;// Thuộc struct A
là Default Initialization, không thuộc một trong các trường hợp của (1)(otherwise, no initialization is performed) và nó không được khởi tạo bởi user-provided constructor nên giá trị của nó sẽ là indeterminate đúng không ạ?quan trọng làĐây thuộc về 2 khái niệm không liên quan gì đến nhau:
- Seg fault ==> Signal, khái niệm của HĐH,
- Try catch ==> Exception, khái niệm của ngôn ngữ C++
Tuy nhiên dev vẫn có thể raise signal trong phần catch exception nếu muốn.
Thanks bác đã share github đúng câu trả lời em cần,Giống như ông bribnt nói đó. segfault là signal. Muốn catch đc nó thì phải viết signal handler. Cái signal handler nó giới hạn nhiều thứ, k viết đc giống như function bt đâu, cẩn thận kẻo ăn hành.
https://stackoverflow.com/questions/1717991/throwing-an-exception-from-within-a-signal-handler
Còn muốn ăn sẵn thì search lib mà xài
https://github.com/Plaristote/segvcatch
![]()
Lần sau có đi hỏi thì một khi ngta đã chỉ cho thì nhớ đọc kỹ đi,Segfault nó crash mịa nó nguyên cái process luôn signal handler cái gì, bác hiểu câu hỏi không?
Là sao bác, công ty bác đang tuyển người hả?mình đang mời ae vào làm cùng nhé, có gì ae giúp nhau. Chứ không phải nói trình mình cao nhé![]()
đúng rồi bác,Là sao bác, công ty bác đang tuyển người hả?
ơ sau khi đọc lại value category của MSnhưng xài rvalue ref vẫn vướng 1 cách truyềnđó là truyền const lvalue vào:![]()
thế là phải viết thêm 1 ctorC++:const std::string default{"default"}; foos.emplace_back(default, 0); // rvalue ref ko bind vào const lvalue được, báo lỗi
Foo(const std::string&, int)
à? Cái này đụng chạm quy luật DRY dont repeat yourselfC++ rác vậy xao![]()
![]()
const std::string default
là lvalue, nhưng mà là non-modifiable lvalue. Mà lvalue thì ko thể biến thành rvalue được. Nhưng chỉ cần tạo 1 biến copy là xong:const std::string default{"default"};
foos.emplace_back(std::string{default}, 0); // std::string{default} là prvalue (ko có identity, có moveable)
trong cái link MS kia có ví dụ rõ ràng hơn, vào đó xem ví dụIf you have (or you can take) the memory address of a value, and use it safely, then the value has identity.
s.substr(1, 2)
là xvalue vậy vì nó sống ko thọ, nhưng thực ra ở đây nó là prvalue #include <utility>
void f(int n) {}
void f(int& n) {}
void f(const int& n) {}
void f(int&& n) {}
int main() {
int n1 = 11;
const int n2 = 22;
f(n1); // lvalue
f(n2); // const lvalue
f(std::move(n1)); // xvalue
f(int{n2}); // prvalue
}
#include <iostream>
struct Category {
Category& whoami() & { std::cout << "ref\n"; return *this; }
const Category& whoami() const& { std::cout << "cref\n"; return *this; }
Category&& whoami() && { std::cout << "rref\n"; return std::move(*this); }
Category() = default;
Category(const Category&) { std::cout << "copy ctor\n"; }
Category(Category&&) { std::cout << "move ctor\n"; }
};
void f1(Category cat) {
std::cout << "pass by value\n";
cat.whoami();
}
void f2(Category& cat) {
std::cout << "pass by ref\n";
cat.whoami();
}
void f3(const Category& cat) {
std::cout << "pass by cref\n";
cat.whoami();
}
void f4(Category&& cat) {
std::cout << "pass by rref\n";
cat.whoami();
}
int main() {
Category cat1;
const Category cat2;
f1(cat1.whoami()); // lvalue
f2(cat1.whoami()); // lvalue
f3(cat1.whoami()); // lvalue
std::cout << "---\n";
f1(cat2.whoami()); // const lvalue
f3(cat2.whoami()); // const lvalue
std::cout << "---\n";
f1(std::move(cat1).whoami()); // xvalue
f3(std::move(cat1).whoami()); // xvalue
f4(std::move(cat1).whoami()); // xvalue
std::cout << "---\n";
f1(Category{}); // prvalue
f3(Category{}); // prvalue
f4(Category{}); // prvalue
std::cout << "---\n";
f1(Category{cat2}); // prvalue
f3(Category{cat2}); // prvalue
f4(Category{cat2}); // prvalue
}
ref
copy ctor
pass by value
ref
ref
pass by ref
ref
ref
pass by cref
cref
---
cref
copy ctor
pass by value
ref
cref
pass by cref
cref
---
rref
move ctor
pass by value
ref
rref
pass by cref
cref
rref
pass by rref
ref
---
pass by value
ref
pass by cref
cref
pass by rref
ref
---
copy ctor
pass by value
ref
copy ctor
pass by cref
cref
copy ctor
pass by rref
ref
cat
ở trỏng. Named rvalue ref = lvalue.cref chắc là constant ref, rref là gì đấy bácơ sau khi đọc lại value category của MSthì toy mới thấy![]()
const std::string default
là lvalue, nhưng mà là non-modifiable lvalue. Mà lvalue thì ko thể biến thành rvalue được. Nhưng chỉ cần tạo 1 biến copy là xong:
prvalue nó bind vào rvalue ref ngon lànhC++:const std::string default{"default"}; foos.emplace_back(std::string{default}, 0); // std::string{default} là prvalue (ko có identity, có moveable)
vậy xài rvalue ref thực ra ngon hơn pass by value ở trường hợp này![]()
---
ban đầu C++ chỉ có 2 value category là lvalue và rvalue. Phân biệt 2 loại này bằng khái niệm identity. 1 biến có identity ở đây nghĩa là biến đó có địa chỉ và có thể sử dụng địa chỉ đó 1 cách an toàn:
trong cái link MS kia có ví dụ rõ ràng hơn, vào đó xem ví dụ![]()
sau này đẻ ra thêm khái niệm moveablethì value category được chia làm 4 loại: i & m, !i & m, i & !m, !i & !m. Nhưng mà !i & !m vô giá trị nên chỉ còn 3 loại thoy:![]()
ngoài ra còn có gộp lại thành 2 category nữa là i và m: i bao gồm i & !m và i & m, gọi là glvalue. m bao gồm i & m và i & !m, gọi là rvalue.
- i & !m: có identity nhưng ko moveable: là lvalue (theo toy nghĩ là giống như lvalue khái niệm cũ)
- !i & m: ko có identity nhưng movable: là prvalue (theo toy nghĩ là giống như rvalue khái niệm cũ)
- i & m: có identity và movable: là xvalue (khái niệm mới)
có identity mà movable thì rất vô lý vì move xong identity cũ đâu còn sử dụng được nữa, vậy theo khái niệm cũ đâu phải là lvaluemà có identity thì cũng đâu phải rvalue khái niệm cũ
đặt tên xvalue như là expiring thì cứ tưởng ví dụ như![]()
s.substr(1, 2)
là xvalue vậy vì nó sống ko thọ, nhưng thực ra ở đây nó là prvaluevì nó ko có địa chỉ sử dụng được nhưng move được, nghĩa là !i & m nghĩa là prvalue. Rồi tự dưng đẻ ra glvalue và rvalue làm gì, đặt tên cũng như l`: rvalue (m) ở trên thì trùng với tên rvalue khái niệm cũ, còn lvalue (i & !m) thì lại trùng khái niệm mới. Sao đéo đổi tên thành i/m luôn cho rồi![]()
![]()
thì nó in ra lỗi:C++:#include <utility> void f(int n) {} void f(int& n) {} void f(const int& n) {} void f(int&& n) {} int main() { int n1 = 11; const int n2 = 22; f(n1); // lvalue f(n2); // const lvalue f(std::move(n1)); // xvalue f(int{n2}); // prvalue }
View attachment 1664468
View attachment 1664469
View attachment 1664482View attachment 1664481
vậy:
lvalue có thể pass vào value, ref, cref: lvalue ko thể truyền vào rref được)
const lvalue có thể pass vào value, cref: const lvalue như lvalue ko thể truyền vào rref được, và có thêm ko truyền vào ref được)
xvalue có thể pass vào value, cref, rref: trừ ref ra
prvalue có thể pass vào value, cref, rref: trừ ref ra
lịt pẹ ko biết tìm official doc phải đi thí nghiệm như du túp bơ ráclần này có thêm marker:
output:C++:#include <iostream> struct Category { Category& whoami() & { std::cout << "ref\n"; return *this; } const Category& whoami() const& { std::cout << "cref\n"; return *this; } Category&& whoami() && { std::cout << "rref\n"; return std::move(*this); } Category() = default; Category(const Category&) { std::cout << "copy ctor\n"; } Category(Category&&) { std::cout << "move ctor\n"; } }; void f1(Category cat) { std::cout << "pass by value\n"; cat.whoami(); } void f2(Category& cat) { std::cout << "pass by ref\n"; cat.whoami(); } void f3(const Category& cat) { std::cout << "pass by cref\n"; cat.whoami(); } void f4(Category&& cat) { std::cout << "pass by rref\n"; cat.whoami(); } int main() { Category cat1; const Category cat2; f1(cat1.whoami()); // lvalue f2(cat1.whoami()); // lvalue f3(cat1.whoami()); // lvalue std::cout << "---\n"; f1(cat2.whoami()); // const lvalue f3(cat2.whoami()); // const lvalue std::cout << "---\n"; f1(std::move(cat1).whoami()); // xvalue f3(std::move(cat1).whoami()); // xvalue f4(std::move(cat1).whoami()); // xvalue std::cout << "---\n"; f1(Category{}); // prvalue f3(Category{}); // prvalue f4(Category{}); // prvalue std::cout << "---\n"; f1(Category{cat2}); // prvalue f3(Category{cat2}); // prvalue f4(Category{cat2}); // prvalue }
thì thấy rref sau khi truyền vào value hoặc rref thì trong thân hàm nó bị biến thành ref nghĩa là nó biến thành lvalue, vì nó được đặt tên làCode:ref copy ctor pass by value ref ref pass by ref ref ref pass by cref cref --- cref copy ctor pass by value ref cref pass by cref cref --- rref move ctor pass by value ref rref pass by cref cref rref pass by rref ref --- pass by value ref pass by cref cref pass by rref ref --- copy ctor pass by value ref copy ctor pass by cref cref copy ctor pass by rref ref
cat
ở trỏng. Named rvalue ref = lvalue.![]()
rvalue ref && ấycref chắc là constant ref, rref là gì đấy bác![]()
ví dụ có 3 lib/exe ở đây: A, B, C. C xài B, B có thể xài hoặc ko xài A.target_include_directories(target_name {PUBLIC|PRIVATE|INTERFACE} directories...)
Thím nào giải thích giúp mình cái scope kia của target_include_directories trong cmake với. Kiến thức cmake mình bằng 0 nên trong lúc học không hiểu nó.