我再次问这个问题,因为唯一的另一个类似问题已经接近10年了,并且包含有关涉及基类子对象的表达式的错误信息:
[defns.dynamic.type]将glvalue的动态类型定义为:
glvalue所引用的最派生对象的类型
glvalue最多只能引用一个对象,并且由于[intro.object] p6定义的“最派生对象” 实质上是:
完整的对象,数据成员或类类型的数组元素,或非类类型的对象称为最派生对象。
如果glvalue不引用最派生的对象,那么动态类型是否不确定?
另外,我知道表达式的动态类型的预期效果是:对于E
引用类型为object的glvalue表达式,该对象是type的对象的B
基类子对象D
,其中B
是的基类D
,以获取类型D
从E
,但是,我看不到当前措辞如何实现甚至不需要实现,因为绑定到派生类类型的基类类型的引用/指针将始终引用基类子对象。据我所知,永远不会发生表达式的类型和它所引用的对象的类型的情况。
我在这些问题上提到了很多StackOverflow链接,其中auto_ptr
不能与STL很好地配合
的原因std::auto_ptr<>
不能满足可复制构造和可分配的要求(因为auto_ptr
有一个伪造的复制构造函数,它基本上可以转移所有权)。
但是,甚至unique_ptr
没有复制ctor和赋值运算符(已禁用),那么如何满足可复制构造和可赋值的要求呢?
鉴于 x86 具有强大的内存模型,是否有必要使用std::memory_order_acquire
fence(不是 operation)?
例如,如果我有这个代码:
uint32_t read_shm(const uint64_t offset) {
// m_head_memory_location is char* pointing to the beginning of a mmap-ed named shared memory segment
// a different process on different core will write to it.
return *(uint32_t*)(m_head_memory_location + offset);
}
....
int main() {
uint32_t val = 0;
while (0 != (val = shm.read(some location)));
.... // use val
}
Run Code Online (Sandbox Code Playgroud)
我真的需要std::atomic_thread_fence(std::memory_order_acquire)
在return语句之前吗?
我觉得没有必要,因为上面代码的目标是尝试从 读取前 4 个字节m_head_memory_location + offset
,因此重新排序栅栏后的任何内存操作都不会影响结果。
或者有一些副作用使获取栅栏变得必要?
在 x86 上是否需要获取栅栏(不是操作)? …
通过阅读标准,我无法确定以下代码是否违反了 ODR:
// a.h
#ifndef A_HEADER_FILE
#define A_HEADER_FILE
namespace {
int v;
}
inline int get_v() { return v; }
#endif // A_HEADER_FILE
// a.cpp
#include "a.h"
void f() {
int i = get_v();
// ...
}
// b.cpp
#include "a.h"
void g() {
int i = get_v();
// ...
}
Run Code Online (Sandbox Code Playgroud)
(来源:https : //wiki.sei.cmu.edu/confluence/display/cplusplus/DCL59-CPP.+Do+not+define+an+unnamed+namespace+in+a+header+file)
据说,get_v()
在每个翻译单元中引用了不同的变量,因此它违反了ODR
。
这个答案:内联函数和外部链接说内联放松ODR
所以我不确定为什么这仍然是一个错误?
如果这是否ODR
违规,有人可以将我链接到标准中指定的位置吗?
c++ one-definition-rule inline-functions linkage language-lawyer
我正在尝试使用 CPP 线程添加偶数和奇数,代码如下所示
typedef unsigned long long ull;
ull EvenSum = 0;
ull OddSum = 0;
void find_Evensum(ull start, ull end)
{
for(ull i=start;i<=end;i++)
{
if((i&1) == 0)
{
EvenSum+=i;
}
}
}
void find_Oddsum(ull start, ull end)
{
for(ull i=start;i<=end;i++)
{
if((i&1) == 1)
{
OddSum+=i;
}
}
}
int main()
{
ull start = 0;
ull end = 1900000000;
auto start_time = high_resolution_clock::now();
#if 0
thread t1(find_Evensum, start, end);
thread t2(find_Oddsum, start, end);
t1.join();
t2.join();
#else
find_Evensum(start, end); …
Run Code Online (Sandbox Code Playgroud) 我对以下代码有点困惑
int main()
{
int* a = new int{12};
int* b = new int;
b = a;
delete a;
delete b;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
该代码返回一个错误
a.out(27538,0x10ade7e00) malloc: *** error for object 0x7f8c18504160: pointer being freed was not allocated
a.out(27538,0x10ade7e00) malloc: *** set a breakpoint in malloc_error_break to debug
zsh: abort ./a.out
Run Code Online (Sandbox Code Playgroud)
我的问题是,当我删除 a 时,它会自动删除 b 吗?这里的机制是什么,我有点迷路了。
注意:在发布问题之前,我已经浏览了有关std::bad_weak_error
while usingshared_from_this
将现有实例的 shared_ptr 传递shared_ptr
给另一个方法的现有问题。它们都与此类似:
shared_from_this()
std::enable_shared_from_this<>
public。以下是重现该错误的示例代码:
#include <iostream>
#include <memory>
class ILogger {
public:
virtual ~ILogger() {}
virtual void Log() = 0;
};
class LogManager;
class Logger : public ILogger {
public:
Logger(std::shared_ptr<LogManager> logManager)
: m_logManager(logManager)
{
}
void Log() override
{
std::cout << "Dump logs";
}
private:
std::shared_ptr<LogManager> m_logManager;
};
class ILogManager {
public:
virtual ~ILogManager() {}
virtual std::shared_ptr<ILogger> GetLogger() = 0;
};
class LogManager : public ILogManager, public …
Run Code Online (Sandbox Code Playgroud) 我在几个地方读到,宽松的排序可以生成唯一的 ID。我对此表示怀疑,因为如果两个线程同时调用:
uniqueId.fetch_add(1, std::memory_order::relaxed);
那么线程 A 递增的值可能对线程 B 不可见。这意味着,两个线程可以获得相同的唯一 ID。
出于这个原因,我宁愿使用std::memory_order::acq_rel
你怎么认为?
在实践中无法测试。
编辑:原始的单词选择令人困惑.术语"象征性"比原始术语("神秘")要好得多.
在关于我以前的C++问题的讨论中,我被告知指针是
这并没有健全的权利!如果没有任何符号,并且指针是其表示,那么我可以执行以下操作.我可以吗?
#include <stdio.h>
#include <string.h>
int main() {
int a[1] = { 0 }, *pa1 = &a[0] + 1, b = 1, *pb = &b;
if (memcmp (&pa1, &pb, sizeof pa1) == 0) {
printf ("pa1 == pb\n");
*pa1 = 2;
}
else {
printf ("pa1 != pb\n");
pa1 = &a[0]; // ensure well defined behaviour in printf
}
printf ("b = %d *pa1 = %d\n", …
Run Code Online (Sandbox Code Playgroud) 这是我在"我不理解C和C++中的指针"集合中的一个新问题.
如果我将具有相同值的两个指针的位混合(指向相同的存储器地址),那恰好具有完全相同的位表示,当一个是可解除引用且一个是结束时,标准说应该发生什么?
#include <stdio.h>
#include <string.h>
#include <assert.h>
// required: a == b
// returns a copy of both a and b into dest
// (half of the bytes of either pointers)
int *copy2to1 (int *a, int *b) {
// check input:
// not only the pointers must be equal
assert (a == b);
// also the representation must match exactly
int *dest;
size_t s = sizeof(dest);
assert(memcmp(&a, &b, s) == 0);
// copy a and b into dest:
// …
Run Code Online (Sandbox Code Playgroud) 首先,一个典型的实施是std::weak_ptr
什么?特别是std::weak_ptr
只是一个控制块的指针std::shared_ptr
?
如果所有std::shared_ptr
引用都消失了,内部控制块是否被删除?如果是这样,std::weak_ptr::expired()
如果重新使用该内存,如何正常运行?
我有一个包含a的对象,std::weak_ptr
我想memcpy
将对象转换为稍后要处理的缓冲区.这样做会以某种方式打破智能指针的内部工作吗?
简介:这个问题是我收集的C和C++(以及C/C++常见子集)问题的一部分,这些问题涉及允许具有严格相同的字节表示的指针对象具有不同的"值",即行为不同对于某些操作(包括在一个对象上定义了行为,在另一个对象上定义了未定义的行为).
在另一个引起很多混淆的问题之后,这里有关于指针语义的问题,希望能够解决问题:
这个程序在所有情况下都有效吗?唯一有趣的部分是在"pa1 == pb"分支中.
#include <stdio.h>
#include <string.h>
int main() {
int a[1] = { 0 }, *pa1 = &a[0] + 1, b = 1, *pb = &b;
if (memcmp (&pa1, &pb, sizeof pa1) == 0) {
int *p;
printf ("pa1 == pb\n"); // interesting part
memcpy (&p, &pa1, sizeof p); // make a copy of the representation
memcpy (&pa1, &p, sizeof p); // pa1 is a copy of the bytes of …
Run Code Online (Sandbox Code Playgroud) c++ ×11
pointers ×5
c++11 ×3
c ×2
shared-ptr ×2
stdatomic ×2
weak-ptr ×2
arrays ×1
atomic ×1
auto-ptr ×1
linkage ×1
lvalue ×1
memcpy ×1
memory-model ×1
performance ×1
stl ×1
subobject ×1
unique-ptr ×1
x86 ×1