簡體   English   中英

std::launder 可達性規則

[英]std::launder reachability rules

std::launder示例具有以下代碼塊:

int x2[2][10];
auto p2 = std::launder(reinterpret_cast<int(*)[10]>(&x2[0][0])); 
// Undefined behavior: x2[1] would be reachable through the resulting pointer to x2[0]
// but is not reachable from the source

什么? 來自std::aligned_storage的示例讓我覺得情況並非如此:

std::aligned_storage_t<sizeof(T), alignof(T)> data[N];

// Access an object in aligned storage
const T& operator[](std::size_t pos) const 
{
    // Note: std::launder is needed after the change of object model in P0137R1
    return *std::launder(reinterpret_cast<const T*>(&data[pos]));
}

這就是混淆的地方: &data[pos]只是&data[pos][0] ,因為&p == &p[0]其中p是一個數組

如果std::aligned_storage除了像alignas(T) std::byte[sizeof (T)];類的其他方式之外幾乎不能以任何其他方式實現,那這怎么行? ? 結構中的數組是否以某種方式神奇地使它變好? 為什么?

假設我有

template <typename T>
using uninitialized = alignas(T) std::byte[sizeof (T)];

constexpr auto N = 5;
uninitialized<int> array[N];
for (std::size_t i = 0; i < N; i++) {
    new (&array[i]) int(i);
}

怎么辦? 是不是任何演員都喜歡

auto laundered_value_ptr = std::launder(reinterpret_cast<int*>(&array[i]));

和第一個例子一樣嗎? 那這個呢:

auto laundered_array_ptr = std::launder(reinterpret_cast<int*>(array));
laundered_array_ptr[0] = 9;
laundered_array_ptr[2] = 76;

如果我遵循,似乎沒有辦法正確使用這個 memory,因為使用std::byte(*)[sizeof (int)]意味着它周圍的任何東西基本上都是可以訪問的,並且在第一個例子之后,所有寫在這個問題是也可能是UB。

我使用g++ -g -O0 -Wextra -Wall -Wpedantic -std=c++20 -fsanitize=undefined -fsanitize=address編譯了這些示例,奇怪的是甚至沒有收到讓我完全難過的警告。

我懷疑這根本不重要,但這是我正在使用的編譯器版本。

g++ (GCC) 12.1.1 20220730

你寫了:

&data[pos]只是&data[pos][0] ,因為&p == &p[0]其中p是一個數組。

事實上,事實並非如此。 如果p是一個數組(將其類型稱為T[N] ),則表達式&p == &p[0]將無法編譯。 左側的類型為T(*)[N] ,右側的類型為T* 這些無法直接比較,就像您無法將int*char*進行比較一樣。

但是, static_cast<void*>(&p) == static_cast<void*>(&p[0])將是真的。

兩個指針代表同一個地址,但不能互相替代。

&data[pos]是指向data一個元素的指針,所有其他data元素都可以通過它訪問。 另一方面,(假設std::aligned_storage_tunsigned char數組的別名) &data[pos][0]僅指向data元素的單個元素; 它並不指向整個data元素。 所以data[pos]的所有其他元素都可以通過它訪問,但data的其他元素不是。

由於data的所有元素都可以通過&data[pos]訪問,因此data中的所有字節都可以通過&data[pos]訪問。 在此指針轉換為const T*后,存儲在data的其他元素中的其他T也可以從結果指針訪問,但這些T的字節也可以從原始指針訪問,所以滿足std::launder的先決條件。

如果我們使用&data[pos][0]作為reinterpret_cast的參數,則只能從該指針訪問單個元素data[pos]中的字節,並且不會滿足先決條件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM