小编Mik*_*Lui的帖子

为什么成员在此示例中未进行零初始化?

这特别是关于C++ 11:

#include <iostream>
struct A {
    A(){}
    int i;
};
struct B : public A {
    int j;
};
int main() {
    B b = {};
    std::cout << b.i << b.j << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

用g ++ 8.2.1编译:

$ g++ -std=c++11 -pedantic-errors -Wuninitialized -O2 a.cpp
a.cpp: In function ‘int main()’:
a.cpp:25:25: warning: ‘b.B::<anonymous>.A::i’ is used uninitialized in this function [-Wuninitialized]
     std::cout << b.i << " " << b.j << std::endl
Run Code Online (Sandbox Code Playgroud)

gcc检测b.i为未初始化,但我认为它应该与零一起进行零初始化b.j.

相信正在发生的事情(特别是C++ 11,来自ISO/IEC工作草案N3337,强调我的):

  • B …

c++ initialization language-lawyer c++11 list-initialization

20
推荐指数
2
解决办法
927
查看次数

列表初始化参考:GCC或Clang是否正确?

鉴于这个例子:

int g_i = 10;
struct S {
    operator int&(){ return g_i; }
};

int main() {
    S s;
    int& iref1 = s; // implicit conversion

    int& iref2 = {s}; // clang++ error, g++ compiles fine:
                      // `s` is converted
                      // to a temporary int and binds with
                      // lvalue reference

    int&& iref3 = {s}; // clang++ compiles, g++ error:
                       // cannot bind rvalue reference
                       // to lvalue
}
Run Code Online (Sandbox Code Playgroud)

错误如评论中所述.
使用gcc 8.2.1clang 7.0.1,并且不同意本例中发生的情况.有人可以澄清一下吗?

在列表初始化中:

否则,如果初始化程序列表具有 …

c++ language-lawyer list-initialization

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

C++20 协程的 Lambda 生命周期解释

Folly为 C++20 风格的协程提供了一个可用的库。

在自述文件中,它声称:

重要提示:您需要非常小心临时 lambda 对象的生命周期。调用 lambda 协程会返回一个 folly::coro::Task 捕获对 lambda 的引用,因此如果返回的 Task 没有立即 co_awaited 那么当临时 lambda 超出范围时,任务将留下悬空引用。

我尝试为他们提供的示例制作 MCVE,但对结果感到困惑。为以下所有示例假设以下样板:

#include <folly/experimental/coro/Task.h>
#include <folly/experimental/coro/BlockingWait.h>
#include <folly/futures/Future.h>
using namespace folly;
using namespace folly::coro;

int main() {
    fmt::print("Result: {}\n", blockingWait(foo()));
}
Run Code Online (Sandbox Code Playgroud)

我用地址消毒剂编译了以下内容,以查看是否有任何悬空引用。

编辑:澄清的问题

问题:为什么第二个示例没有触发 ASAN 警告?

根据cppreference

当协程到达 co_return 语句时,它执行以下操作:

...

  • 或为 co_return expr 调用 promise.return_value(expr),其中 expr 具有非 void 类型
  • 以与创建它们相反的顺序销毁所有具有自动存储持续时间的变量。
  • 调用 promise.final_suspend() 和 co_await 的结果。

因此,也许临时 lambda 的状态在返回结果之前实际上不会被破坏,因为foo它本身是一个协程?


ASAN 错误:我假设在等待协程时“i”不存在

auto foo() -> …
Run Code Online (Sandbox Code Playgroud)

c++ folly c++20 c++-coroutine

9
推荐指数
1
解决办法
1911
查看次数

恢复生命周期已经结束的对象的成员函数协程是UB吗?

这个问题源于这个评论:C++20 协程的 Lambda 生命周期解释

关于这个例子:

auto foo() -> folly::coro::Task<int> {
    auto task = []() -> folly::coro::Task<int> {
        co_return 1;
    }();
    return task;
}
Run Code Online (Sandbox Code Playgroud)

所以问题是执行返回的协程是否foo会导致UB。

“调用”成员函数(在对象的生命周期结束后)是 UB:http : //eel.is/c++draft/basic.life#6.2

...任何表示对象将位于或曾经位于的存储位置地址的指针都可以使用,但只能以有限的方式使用。[...] 程序有未定义的行为,如果:

[...]

-- 指针用于访问非静态数据成员或调用对象的非静态成员函数,或

但是,在这个例子中:

  • ()lambda 的生命周期仍然有效时调用 lambda的运算符
  • 然后暂停,
  • 然后 lambda 被破坏,
  • 然后成员函数(operator ())在之后的某个时间点恢复。

此恢复是否被视为未定义行为?

c++ language-lawyer c++20 c++-coroutine

8
推荐指数
1
解决办法
251
查看次数

Windows 7 命令提示符是否有等价的 stdbuf?

所以 gnu 有 stdbuf 允许你修改命令的 I/O 流的缓冲。我需要相同的命令提示符功能,但我似乎找不到任何关于它的信息。

我只是尝试将程序的 stdout 和 stderr 输出到日志文件,而不进行缓冲(或者更确切地说,只是为了使它们同步并以与在控制台中显示的顺序相同的顺序显示)。

我是否只是错过了一些明显的命令或语法,或者我只是在 Windows 中不走运?

stdout stderr io-redirection

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

对齐如何与指向零大小数组的指针一起工作?

我正在研究一些我看到的处理0大小数组的代码.具体来说,它们用于动态分配结构大小的情况,例如https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html

具体来说,这是Callgrind中的代码:

struct _EventGroup {
    int size;
    const char* name[0];
};
Run Code Online (Sandbox Code Playgroud)

我正在玩这个,在64位Red Hat上使用gcc 4.1.2,并注意到当name字段是一个指针时,sizeof函数返回整个struct _EventGroup的大小为8个字节.现在,如果我将其更改为:

struct _EventGroup {
    int size;
    const char name[0];
};
Run Code Online (Sandbox Code Playgroud)

我得到4个字节,因为gcc将0大小的数组标识为不占用空间,而int占用4个字节.那讲得通.如果我然后将其更改为:

struct _EventGroup {
    int size;
    const char* name;
};
Run Code Online (Sandbox Code Playgroud)

sizeof返回16个字节,因为char*在64位系统中占用8个字节,并且int必须填充到8个字节.这是有道理的.现在,如果我做最后一次改变:

struct _EventGroup {
    const char* name[0];
};
Run Code Online (Sandbox Code Playgroud)

我得到0字节因为gcc检测到我的零大小数组.我要澄清的是在我提出的第一个案例中发生了什么.gcc为指向零大小数组的指针分配了多少空间?为什么?我问,因为这个代码看起来设计为内存分配效率很高,但是如果gcc检测到它指向基本上什么都没有,那么gcc要么指定大小为0字节,要么如果它被视为一个普通的指针.对齐将指示我使用原始结构获得4个字节或16个字节.为什么我得到8个字节?

c gcc struct sizeof

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

这是否适合在C中使用const限定符?

我在C中有一个简单的向量实现,它包含一个void*数组.由用户来决定实际类型.

我想'保证'向量不会改变其内容,所以我将数据存储为:

Struct _Vector{
    UInt32 used;
    UInt32 size;
    const void** arr;
};
Run Code Online (Sandbox Code Playgroud)

我不知道它是否被认为是"过度使用"我的常量正确性,但我尝试用我的访问器/修饰符来维持const正确性:

void vector_add(Vector *v, const void* const elem);   
void vector_set(Vector *v, const UInt32 idx, const void* const elem);
Run Code Online (Sandbox Code Playgroud)

当我从向量中返回一个元素时,它是一个指向用户数据的指针,所以我让用户通过丢弃内部数组中的常量来修改指向的数据.

void* vector_get(const Vector *v, const UInt32 idx){
    if ( idx >= v->used ) 
        exitAtError("Vector","Array out of bounds");
    return (void*)v->arr[idx];
}
Run Code Online (Sandbox Code Playgroud)

而不是返回const void*,而是返回void*.我的想法是在内部,我想确保我没有改变所指向的数据,但我不关心向量之外的数据会发生什么.

这被认为是const的正确用法吗?我认为在一个地方将数据声明为const是可以的,同时在其他地方将其变为可变.在阅读了许多声称永远不会抛弃constness的教​​条文章后,我不确定,如果它被丢弃,那么使用const是不合适的.

c const

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

在单独的线程中与类型的构造函数并行运行成员函数是否是未定义的行为?

这是你不应该做的场景,但https://timsong-cpp.github.io/cppwp/class.cdtor#4指出:

成员函数,包括虚函数([class.virtual]),可以在构造或销毁([class.base.init])期间调用。

如果并行调用这些函数,这是否成立?也就是说,忽略竞争条件,如果A正在构造过程中,并且frobme在构造函数被调用之后的某个时间点被调用(例如在构造过程中),那仍然是定义的行为吗?

#include <thread>

struct A {
    void frobme() {}
};

int main() {
    char mem[sizeof(A)];

    auto t1 = std::thread([mem]() mutable { new(mem) A; });
    auto t2 = std::thread([mem]() mutable { reinterpret_cast<A*>(mem)->frobme(); });

    t1.join();
    t2.join();
}
Run Code Online (Sandbox Code Playgroud)

作为一个单独的场景,有人还向我指出, 的A构造函数可以创建多个线程,这些线程可能会A在构造完成之前调用成员函数函数,但是这些操作的顺序会更易于分析(您知道在构造函数中生成线程之后才会发生竞争)。

c++ constructor race-condition object-lifetime language-lawyer

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