相关疑难解决方法(0)

为什么`&array`和`array`指向同一个地址?

到现在为止,我认为数组与指针相同.但我发现了一个奇怪的案例:

int array[5] = { 10,11,12,13,14};

std::cout << array << std::endl;
std::cout << &array << std::endl;
std::cout << &array[0] << std::endl;

int *pArray = new int[5];

std::cout << pArray << std::endl;
std::cout << &pArray << std::endl;
std::cout << &pArray[0] << std::endl;
Run Code Online (Sandbox Code Playgroud)

产量

0x7ffeed730ad0
0x7ffeed730ad0
0x7ffeed730ad0

0x7f906d400340
0x7ffeed730a30
0x7f906d400340
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,array并且&array具有相同的价值.但是pArray并且&pArray有不同的价值.如果数组与指针相同,则数组的地址应与数组不同.怎么可能array&array是一样的?如果array&array相同,保存数组值的内存的地址是什么?

c++ arrays pointers

51
推荐指数
1
解决办法
3258
查看次数

指针可互换性与具有相同的地址

标准N4659工作草案说:

[basic.compound]
如果两个对象是指针可互换的,那么它们具有相同的地址

然后注意到

数组对象及其第一个元素不是指针可互换的,即使它们具有相同的地址

使数组对象及其第一个元素非指针可互换的基本原理是什么?更一般地说,区分指针 - 可互换性概念与具有相同地址的概念的理由是什么?在那里某处不存在矛盾吗?

看来,给定这一系列陈述

int a[10];

void* p1 = static_cast<void*>(&a[0]);
void* p2 = static_cast<void*>(&a);

int* i1 = static_cast<int*>(p1);
int* i2 = static_cast<int*>(p2);
Run Code Online (Sandbox Code Playgroud)

p1 == p2但是,我们已经i1明确定义并且使用i2会导致UB.

c++ arrays pointers language-lawyer c++17

24
推荐指数
1
解决办法
1080
查看次数

如何解释std :: launder的可达性要求?

std::launder函数要求通过结果可以访问的每个字节都可以通过参数访问。“可达到”的定义如下:

通过一个指向对象Y的指针值可以到达一个存储字节,如果该对象位于Y所占的存储空间之内,则该对象可以与Y进行指针可互转换;如果Y是一个数组元素,则该数组将立即包含在数组对象中。

根据对另一个问题的回答,此限制“ ...意味着您将无法launder获得一个指针,该指针将允许您访问比源指针值允许更多的字节,这将带来不确定的行为。”

这对于TC给出的示例是有意义的,但是在原始对象已被新对象替换的情况下,我不理解如何解释它,这是预期的原始目的std::launder。该标准具有以下示例:

struct X { const int n; };
X *p = new X{3};
const int a = p->n;
new (p) X{5}; // p does not point to new object (6.8) because X::n is const
const int b = p->n; // undefined behavior
const int c = std::launder(p)->n; // OK
Run Code Online (Sandbox Code Playgroud)

在这种情况下,到时间std::launder被调用时,由p- 指向的对象--原始X对象--已经不存在,因为在其所占用的存储中创建新对象已隐式结束了其生命周期([基本。生活] /1.4)。因此,似乎有通过任何字节可达p因为 …

c++ language-lawyer c++17 stdlaunder

15
推荐指数
1
解决办法
234
查看次数

Is converting a reinterpret_cast'd derived class pointer to base class pointer undefined behavior?

Have a look at is simple example:

struct Base { /* some virtual functions here */ };
struct A: Base { /* members, overridden virtual functions */ };
struct B: Base { /* members, overridden virtual functions */ };

void fn() {
    A a;
    Base *base = &a;
    B *b = reinterpret_cast<B *>(base);
    Base *x = b;
    // use x here, call virtual functions on it
}
Run Code Online (Sandbox Code Playgroud)

Does this little snippet have Undefined Behavior?

reinterpret_cast定义明确,它返回的值不变base,只是类型为B …

c++ language-lawyer

11
推荐指数
1
解决办法
346
查看次数

std :: launder与reinterpret_cast一起使用

今天在回答" 基于堆的分配数组的循环范围 "的问题时,我偶然发现了使用reinterpret_cast从指针类型转换为数组类型的建议std::launder(经过一些讨论我们决定发布一个新问题,因为我们不能找到结论.)演员如下完成(例如,为了能够使用基于范围的循环迭代数组):

int* ptr = new int[3];
auto arr_ptr = std::launder(reinterpret_cast<int (*)[3]>(ptr));
Run Code Online (Sandbox Code Playgroud)

我几乎可以肯定这是UB,但我不太确定.有没有人在C++中足够坚定地回答这个问题?

我认为这可以解释为什么reinterpret_cast在从ptr-type转换为array-type(我认为是UB)时是否有效,并且无论我是否使用它都没有std::launder.

c++ language-lawyer reinterpret-cast

10
推荐指数
0
解决办法
113
查看次数

将char指针传递给接受char数组引用的函数

我正试图称这种方法

#define SIZE 16
void DoSomething(char(&value)[SIZE])
{
}
Run Code Online (Sandbox Code Playgroud)

从这个方法:

void BeforeDoingSomething(char* value, int len)
{
    if (len == SIZE)
    {
        DoSomething(value);
    }
}
Run Code Online (Sandbox Code Playgroud)

试图这样做会给我这个错误:

不能使用"char*"类型的值初始化类型为"char(&)[16]"(非const限定)的引用

有关如何让编译器接受value函数传递的任何提示BeforeDoingSomething

c++

10
推荐指数
1
解决办法
721
查看次数

std::launder 与放置 - 新的可达性条件

std::launder有一个先决条件:从将要返回的指针可到达的所有字节都可以通过传递的指针到达。

我的理解是,这是为了允许编译器优化,以便例如

struct A {
    int a[2];
    int b;
};

void f(int&);

int g() {
    A a{{0,0},2};
    f(a.a[0]);
    return a.b;
}
Run Code Online (Sandbox Code Playgroud)

可以优化为始终返回2。(请参阅指针可互换性与具有相同地址能否使用 std::launder 将对象指针转换为其封闭数组指针?


这是否意味着可达性先决条件也应该适用于placement-new?否则有什么阻止我写f如下吗?:

void f(int& x) {
    new(&x) A{{0,0},0};
}
Run Code Online (Sandbox Code Playgroud)

的地址与 的地址a.a[0]相同,a并且新A对象可以透明地替换为旧A对象,因此a.bing现在应该是0

c++ placement-new language-lawyer stdlaunder

6
推荐指数
0
解决办法
382
查看次数

如何解释 std::launder 的前提条件?

struct X { int n; };
const X *p = new const X{3};  // #1
new (const_cast<X*>(p)) const X{5};  // #2
const int c = std::launder(p)->n; 
Run Code Online (Sandbox Code Playgroud)

假设在 处创建的对象#1名为 ,obj1而在 处创建的对象#2名为obj2。的前提std::launder

[ptr.launder] p2链接

p代表内存中一个字节的地址A。处于其生命周期内且类型与 T 类似的对象 X 位于地址 A 处。通过结果可访问的所有存储字节都可通过 p (见下文)访问

如果存在对象 Z,则可以通过指向对象 Y 的指针值访问存储 b 的字节,并且该对象可与 Y 进行指针互换,这样 b 位于 Z 占用的存储空间内,或者如果 Z 则位于直接封闭的数组对象内是一个数组元素。

这个规则有点晦涩难懂。以下解释正确吗?

obj2sizeof(X)将占用以 开头的字节数A。将Y(指向的对象std::launder(p)) 和 …

c++ language-lawyer stdlaunder

5
推荐指数
1
解决办法
225
查看次数