thảo luận [C++] Thớt bàn luận, hỏi đáp thắc mắc về C++

  • Người tạo chủ đề Người tạo chủ đề luiz
  • Ngày bắt đầu Ngày bắt đầu
Cái này là do strong exception guarantee. Tức là nếu exception xảy ra thì cái container phải đc đảm bảo state của nó như lúc chưa gọi cái push_back. Nên nếu move constructor mà k đảm là k có exception thì nó k gọi. Vì move rồi mà có exception thì còn cái nịt, sao mà recover lại đc. Nó phải gọi copy thôi. Tạo ra cái mới. Giữ nguyên cái cũ, exception xảy ra thì như chưa có chuyện gì xảy ra,:beauty:.
https://en.cppreference.com/w/cpp/container/vector/push_back
ừm ờm thêm cái strong exception guarantee này nữa
3296-pepesusthink.png
cái toy đề cập là basic exception guarantee thoy, 1 trong các điều kiện của nó là có exception thì phải bảo đảm ko có leak mem. Strong exception guarantee thì còn có ràng buộc kĩ hơn basic nữa: https://en.cppreference.com/w/cpp/language/exceptions#Exception_safety

lắm ngôn từ bí hiểm
aVgiONl.png
 
Sửa lần cuối:
ừm ờm thêm cái strong exception guarantee này nữa
3296-pepesusthink.png
cái toy đề cập là basic exception guarantee thoy, 1 trong các điều kiện của nó là có exception thì phải bảo đảm ko có leak mem. Strong exception guarantee thì còn có ràng buộc kĩ hơn basic nữa: https://en.cppreference.com/w/cpp/language/exceptions#Exception_safety

lắm ngôn từ bí hiểm
aVgiONl.png
C++:
void rvalue_ref(int &&i) { // (1)
  std::cout << i;
}

void lvalue_ref(const int &i) { //(2)
  std::cout << i;
}

Không biết cái (1) có tạo biến ngầm như cái (2) không thím Kân?
 
C++:
void rvalue_ref(int &&i) { // (1)
  std::cout << i;
}

void lvalue_ref(const int &i) { //(2)
  std::cout << i;
}

Không biết cái (1) có tạo biến ngầm như cái (2) không thím Kân?
hình như cả 2 cái đều tạo biến ngầm khi gọi std::cout<<
0KSdPUp.png

mà chỉ là biến int thì có khi còn lẹ hơn là ko tạo

nếu thay int bằng std::string thì nó ko tạo biến ngầm, hàm std::ostream& operator<<(std::ostream, const std::string&) nó truyền const& đâu có tạo copy nào
 
C++:
class A {
public:
  A(){};
};

class B {
public:
  B() = default; // Từ c++ 11
};

Mọi người cho mình hỏi điều khác biệt khi thêm từ khóa default vào constructor với?
 
C++:
class A {
public:
  A(){};
};

class B {
public:
  B() = default; // Từ c++ 11
};

Mọi người cho mình hỏi điều khác biệt khi thêm từ khóa default vào constructor với?
Cái này là một tính năng từ c++11 thêm vào để nói cho compiler là gen ra giùm mình mấy cái hàm rule of 5 để mình khỏi phải tự code đó. Bình thường thì compiler sẽ tự gen ra nhưng khi tự define 1 trong 5 hàm kia thì cái tính năng gen sẽ bị ngắt nên mình phải tự implement hết mấy cái còn lại rất mất thời gian.
 
Cái này là một tính năng từ c++11 thêm vào để nói cho compiler là gen ra giùm mình mấy cái hàm rule of 5 để mình khỏi phải tự code đó. Bình thường thì compiler sẽ tự gen ra nhưng khi tự define 1 trong 5 hàm kia thì cái tính năng gen sẽ bị ngắt nên mình phải tự implement hết mấy cái còn lại rất mất thời gian.
Em biết vấn đề là tự define thì phải explicitly define những cái còn lại rồi. Nhưng ý chính em đang băn khoăn là nếu define thì dùng cách trên hay cách dưới và ưu nhược điểm nó là gì. Em mò stackoverflow thì answer vòng vo quá mà trình em thì gà.
4gmOAMB.png
 
Em biết vấn đề là tự define thì phải explicitly define những cái còn lại rồi. Nhưng ý chính em đang băn khoăn là nếu define thì dùng cách trên hay cách dưới và ưu nhược điểm nó là gì. Em mò stackoverflow thì answer vòng vo quá mà trình em thì gà.
4gmOAMB.png
prefer = default nha: C.80: Use =default if you have to be explicit about using the default semantics

nó ví dụ cho copy ctor, assignment operator nhưng áp dụng cho default ctor cũng được nha: C.45: Don’t define a default constructor that only initializes data members; use in-class member initializers instead
vd người ta viết ở đây: C.43: Ensure that a copyable class has a default constructor

ví dụ
C++ cũ thì default ctor viết thế này, có thể bất tiện:
C++:
struct A {
    std::string s;
    int n;
    double f;
    A() : s{"default"}, n{11}, f{2.2} {}
    A(const std::string& s, int n) : s{s}, n{n} {} // quên `f`
    A(int n, double f) : s{"default"}, n{n}, f{f} {} // ko quên `s` nhưng "default" bị lặp lại
};
C++ mới thì init ngay tại chỗ khai báo biến luôn:
C++:
struct A {
    std::string s{"default"};
    int n{11};
    double f{2.2};
    A() = default; // buộc phải viết default ctor vì có 2 user-defined ctors ở dưới
                   // vẫn prefer A() = default ở đây hơn là ctor rỗng A() {}
    A(const std::string& s, int n) : s{s}, n{n} {} // quên `f`, ko sao, `f` default là 2.2
    A(int n, double f) : n{n}, f{f} {} // bỏ `s` ko sao
};

---

gõ Ctrl+F () {} thì thấy có dòng virtual ~My_interface() {} // or =default đáng tiếc trong core guidelines này vẫn còn xài () {}
WawmAwM.png
ở nhiều chỗ. Chỗ này có comment lại xài từ "or" chứ ko phải từ "prefer"
WawmAwM.png


---

edit: theo comment này https://stackoverflow.com/a/20828970 thì (){} khác với =default ở chỗ (){} được xem như là user-defined ctor, nghĩa là class có (){} sẽ ko phải là trivial, khác biệt hơi lớn
ghXpJrI.png

default ctor thì trivial vs non-trivial có lẽ ko khác biệt mấy, nhưng với dtor thì nếu dtor là non-trivial thì khi free 1 mảng nó sẽ gọi thêm dtor cho n phần tử trong mảng đó, trong khi nếu dtor là trivial thì nó ko cần gọi dtor cho n phần tử. Tuy vậy nhưng có optimize thì có lẽ nó cũng bỏ qua hết n cái dtor rỗng này nên cùng lắm mất thêm mấy mili giây lúc build
zQU2cJa.png


nếu bỏ viết mấy cái default được thì bỏ qua: C.20: If you can avoid defining default operations, do
còn nếu buộc phải viết thì xài = default cho bảo đảm giống với những gì trình dịch nó tự viết
 
Sửa lần cuối:
ghXpJrI.png

default ctor thì trivial vs non-trivial có lẽ ko khác biệt mấy,

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.

1) if T is a class type with no default constructor or with a user-provided or deleted (since C++11) default constructor, the object is default-initialized;

2) if T is a class type with a default constructor that is neither user-provided nor deleted (since C++11) (that is, it may be a class with an implicitly-defined or defaulted default constructor), the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized;

3) if T is an array type, each element of the array is value-initialized;

4) otherwise, the object is 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.
 
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.
nick xịn bị ban hết ròi ko lai được
zFNuZTA.png

cái kiểu a{}a được zero-init thì chắc giống với array gì đó nhỉ
uzQb2yt.png
viết biến primitive nào trong class cứ phải init hết cho lành
pzGVwuf.png

à bữa vào discord cũng tưởng int n{}; thì n ko được init, bị tụi nó sửa là n bảo đảm = 0 vậy mà vẫn ko nhớ
LTT2cUR.png
 
Sửa lần cuối:
nick xịn bị ban hết ròi ko lai được
zFNuZTA.png

cái kiểu a{}a được zero-init thì chắc giống với array gì đó nhỉ
uzQb2yt.png
viết biến primitive nào trong class cứ phải init hết cho lành
pzGVwuf.png

à bữa vào discord cũng tưởng int n{}; thì n ko được init, bị tụi nó sửa là n bảo đảm = 0 vậy mà vẫn ko nhớ
LTT2cUR.png
Thím cho cái discord invite link cái server c++ thím đang chơi với
6YMZAVl.png
 
nick xịn bị ban hết ròi ko lai được
zFNuZTA.png

cái kiểu a{}a được zero-init thì chắc giống với array gì đó nhỉ
uzQb2yt.png
viết biến primitive nào trong class cứ phải init hết cho lành
pzGVwuf.png

à bữa vào discord cũng tưởng int n{}; thì n ko được init, bị tụi nó sửa là n bảo đảm = 0 vậy mà vẫn ko nhớ
LTT2cUR.png

int n{} là thuộc vào case 4 của cái value-initialized, tức là sẽ gọi vào zero-initialized.
Còn với kiểu class thì zero-initialized hay không tùy thuộc vào nó có implicit default construction / defaulted default constructor hay không.
 
Có thím nào cho em hỏi cái g++ -fexception nó khác với không có exception như thế nào không,
Theo em test thì try catch trong C++ thì nó cùng 1 process nên nếu không có -fexception thì nó không handle được segfault thì phải?
 
không bật thì vẫn try-catch bình thường, có điều không handle được segfault
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++.
 

Thống kê chủ đề

Ngày tạo
luiz,
Người trả lời cuối
No1Crab,
Trả lời
1.008
Lượt xem
116.258
Quay lại
Lên đầu trang