Hỏi về biến kiểu auto trong C++ 11

Theo mềnh biết thì biến kiểu auto được hỗ trợ trong C++11. Biến kiểu auto có thể tự động hiểu mọi kiểu dữ liệu của giá trị khi nó được gán.
VD: auto x = "Day Nhau Hoc"

Nhưng ngoài ưu điểm trên thì còn cái gì khác không anh em ?

Sách dạy C++ của mềnh k có nới điều này nên giờ mới biết … Thật là vi diệu :joy:
Ưu điểm :
Lợi ích của auto trong C++11 là khá lớn trong việc tăng tốc phát triển ứng dụng. Đôi lúc các kiểu dữ liệu rất to lớn và dài, việc sử dụng “tự động chọn kiểu” như auto sẽ giúp cho code ngắn gọn vì “dù gì cũng phải gõ lại đúng kiểu”, bớt các công việc tay chân, như ví dụ trên ta thấy list::iterator là kiểu dữ liệu gõ khá dài. Ví dụ: Concurrency::task<Platform::Array^> (trích trong một project mẫu của Direct3D Windows Phone 8 với XAML).

Nhược điểm của loại biến này là sự không tường minh trong mã nguồn, gây ra việc khó tra cứu nguồn gốc (kiểu dữ liệu) của một biến.

Trích từ : https://www.stdio.vn/articles/read/54/c11-tu-khoa-auto

5 Likes

Một vấn đề mình gặp phải với kiểu auto khi dùng vòng for duyệt qua một vector.
Đang rất là xoắn não :slight_smile:

std::wstring input = L"172.26.3.3";

std::vector<std::wstring> ips = {
L"172.26.3.3",
L"172.26.3.3",
L"172.26.3.3"};

bool exist = false;
for(auto ip:ips){
   if(ip==input){
        exist=true;
        break;
    }
}
// kết quả khi thực hiện xong vòng lặp nhiều lần thì vẫn có trường hợp exist = false.
// Nếu thực hiện lặp với index như truyền thống thì nó hoạt động cho kêt quả chính xác.
3 Likes

Nghe hư cấu quá, 2 cái gần như nhau làm sao xảy ra kết quả khác nhau được.

Vả lại tìm x trong y thì xài std::find chứ tội gì phải viết vòng for thế kia :V

2 Likes

Vừa dính hồi chiều xong, đang chạy bất thình lình lỗi. Thực ra không phải vector wstring mà là một vector đối tượng. Trong đối tượng có 1 trường là wstring và muốn return đối tượng ra.

có thể là do copy ctor có vấn đề, for(auto ip:ips) thì ip là 1 copy của ips[i] nên chỉ khác ips[i] chỗ này thôi (khác nếu copy ctor có vấn đề). Thử thêm 1 dấu & for(auto& ip:ips) để ip chính là ips[i] coi còn lỗi ko :V

5 Likes

Vầy mới ổn :smiley: không có & thì nó copy n lần.

3 Likes

Chưa hết. Để chắc ăn mình cho show 2 thằng wstring của ip và input ra kèm luôn độ dài của 2 wstring.
Kết quả 2 wstring dài bằng nhau và giống y đúc nhau nhưng vẫn không nhảy vào if.

Lạ cái nữa là với vẫn dữ liệu đó thì lần chạy sau (gọi lần sau) có thể nhảy vào if rồi lại bất thình lình ngẫu nhiên không nhảy vào. Đến nhọc.
Mai nếu có thời gian mình quay màn hình cho các bạn xem :thinking:

3 Likes

À mình chợt nhớ ra. Các phần tử trong ips là tham trị. Đúng là nó sẽ copy ra nhưng dữ liệu copy này nó sẽ bị thu hồi ngay khi thoát for (mình từng đọc được warning nói như vậy).
Có thể lý do vì sao trong for mình gán :

pointer = &ip;

Nhưng khi thoát for kiểm tra lại pointer vẫn = nullptr.
Chứ không phải là không nhảy vào if.
Có thể do ip bị thu hồi nhưng vùng nhớ đó có thể được hoặc chưa đươc cấp phát nên mới sinh ra kết quả khi đúng khi sai.

1 Like

vậy là ko phải gán exists = true mà gán pointer = &ip à? :V

nếu vậy thì đúng là bị lỗi đó rồi, thoát khỏi vòng lặp ip bị thu hồi nên pointer trỏ vào vùng nhớ đã bị thu hồi, lúc chạy được lúc chạy ko được đúng triệu chứng rồi :V

vector thì đừng nên reference kiểu pointer như vậy, lỡ có push_back ips nó thay đổi capacity, nó copy mảng cũ sang mảng mới bự hơn thì mấy cái pointer tới phần tử cũ cũng trỏ vào vùng nhớ đã bị thu hồi, cũng chạy sai như vậy :V Xài 1 cái size_t p lưu index của phần tử đó rồi gọi ips[p] thì chắc ăn hơn :V

thứ nhất là thêm & vào: auto&
thứ hai là xài size_t thay cho pointer, lấy index của ip trong ips bằng cách này: std::distance(&ips[0], &ip)

cái đó là cách chữa cháy, còn cách khác xài thư viện <algorithm> thì thế này:

auto it = std::find(begin(ips), end(ips), input);
size_t index = -1;
if (it != end(ips))
    index = std::distance(begin(ips), it);
else
    //ko tìm thấy

hoặc xài thẳng it như con trỏ: *it luôn ko cần gán cái index làm gì, nếu sau đó ko có push_back gì vào ips nữa :V

có cách Pythonista nữa: http://reedbeta.com/blog/python-like-enumerate-in-cpp17/ thì viết thế này:

for (auto [i, ip] : enumerate(ips))
{
    // i là index, ip là ips[i] 
}

ko cần auto& ở đây luôn :V :V :V :V

C++17 phong cách Python :V :V :V
http://coliru.stacked-crooked.com/a/ec5a5b8c34fc9eea

#include <tuple>
#include <vector>
#include <string>
#include <iostream>

template <typename T,
          typename TIter = decltype(std::begin(std::declval<T>())),
          typename = decltype(std::end(std::declval<T>()))>
constexpr auto enumerate(T&& iterable)
{
    struct iterator {
        size_t i;
        TIter iter;
        bool operator!=(const iterator& other) const { return iter != other.iter; }
        void operator++() { ++i; ++iter; }
        auto operator*() const { return std::tie(i, *iter); }
    };
    struct iterable_wrapper {
        T iterable;
        auto begin() { return iterator{ 0, std::begin(iterable) }; }
        auto end() { return iterator{ 0, std::end(iterable) }; }
    };
    return iterable_wrapper{ std::forward<T>(iterable) };
}

int main()
{
    std::wstring input = L"172.26.3.3";

    std::vector<std::wstring> ips = {
        L"172.26.3.1",
        L"172.26.3.3",
        L"172.26.3.3",
    };
    
    size_t index = -1;
    for (auto [i, ip] : enumerate(ips))
    {
        if (ip == input)
        {
            index = i;
            break;
        }
    }
    std::cout << index;
}
4 Likes

Nhiều cái như resize vector đúng là mình chưa ngờ tới. Cảm ơn anh em đã thông não :slight_smile:

1 Like
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?