C和C++中未定义,未指定和实现定义的行为有什么区别?
c c++ undefined-behavior unspecified-behavior implementation-defined-behavior
一般概念似乎与正确使用的拥有原始指针相比没有时间开销,只要std::unique_ptr有足够的优化.
但是std::unique_ptr,特别是在复合数据结构中使用std::vector<std::unique_ptr<T>>呢?例如,调整矢量的基础数据的大小,这可能发生在push_back.各地要隔离性能,我环路pop_back,shrink_to_fit,emplace_back:
#include <chrono>
#include <vector>
#include <memory>
#include <iostream>
constexpr size_t size = 1000000;
constexpr size_t repeat = 1000;
using my_clock = std::chrono::high_resolution_clock;
template<class T>
auto test(std::vector<T>& v) {
    v.reserve(size);
    for (size_t i = 0; i < size; i++) {
        v.emplace_back(new int());
    }
    auto t0 = my_clock::now();
    for (int i = 0; i < repeat; i++) {
        auto back = std::move(v.back()); …在C++中,这段代码是否正确?
#include <cstdlib>
#include <cstring>
struct T   // trivially copyable type
{
    int x, y;
};
int main()
{
    void *buf = std::malloc( sizeof(T) );
    if ( !buf ) return 0;
    T a{};
    std::memcpy(buf, &a, sizeof a);
    T *b = static_cast<T *>(buf);
    b->x = b->y;
    free(buf);
}
换句话说,是*b一个生命已经开始的对象?(如果是的话,它什么时候开始呢?)
免责声明:这是试图深入研究一个更大的问题,所以请不要挂断该示例在实践中是否有任何意义.
并且,是的,如果要复制对象,请使用/提供复制构造函数.(但请注意,即使该示例也不会复制整个对象;它会尝试在几个相邻(Q.2)整数上显示一些内存.)
给定C++ 标准布局 struct,我可以使用一次memcpy写入多个(相邻)子对象吗?
完整示例:(https://ideone.com/1lP2Gd  https://ideone.com/YXspBk)
#include <vector>
#include <iostream>
#include <assert.h>
#include <inttypes.h>
#include <stddef.h>
#include <memory.h>
struct MyStandardLayout {
    char mem_a;
    int16_t num_1;
    int32_t num_2;
    int64_t num_3;
    char mem_z;
    MyStandardLayout()
    : mem_a('a')
    , num_1(1 + (1 << 14))
    , num_2(1 + (1 << 30))
    , num_3(1LL + (1LL << 62))
    , mem_z('z')
    { }
    void print() const {
        std::cout << 
            "MySL Obj: " <<
            mem_a << " / " …我最近发现了vreinterpret {q} _dsttype_srctype转换运算符.但是,这似乎不支持此链接(页面底部)中描述的数据类型的转换:
一些内在函数使用以下形式的向量类型数组:
<type><size>x<number of lanes>x<length of array>_t这些类型被视为包含名为val的单个元素的普通C结构.
示例结构定义是:
Run Code Online (Sandbox Code Playgroud)struct int16x4x2_t { int16x4_t val[2]; };
你知道如何转换uint8x16_t成uint8x8x2_t?
请注意,使用union无法可靠地解决问题(从非活动成员读取导致未定义的行为编辑:这只是C++的情况,而事实证明C允许类型惩罚),也没有使用指针来强制转换(打破严格别名规则).
第19.3节呈现了一章,其主要重点是运算符重载的字符串表示,特别是特种作业[],->和().它实现了copy_from()如下的辅助功能:
void String::copy_from(const String &x)
    // make *this a copy of x
{
    if (x.sz <= short_max)
    {
        memcpy(this, &x, sizeof(x);
        ptr = ch;
    }
    else
    {
        ptr = expand(x.ptr, x.sz+1);
        sz = x.sz;
        space = 0;
    }
}
类接口如下所示:
#ifndef STRING_EXERCISE_H
#define STRING_EXERCISE_H
namespace simple_string
{
    class String;
    char *expand(const char *ptr, int n);
}
class String
{
    public:
        String(); // default constructor x{""}
        explicit String(const char *p); // constructor from …我接管了一些代码,并遇到了一个奇怪的数组重新分配。这是一个 Array 类中的函数(由 JsonValue 使用)
void reserve( uint32_t newCapacity ) {
    if ( newCapacity > length + additionalCapacity ) {
        newCapacity = std::min( newCapacity, length + std::numeric_limits<decltype( additionalCapacity )>::max() );
        JsonValue *newPtr = new JsonValue[newCapacity];
        if ( length > 0 ) {
            memcpy( newPtr, values, length * sizeof( JsonValue ) );
            memset( values, 0, length * sizeof( JsonValue ) );
        }
        delete[] values;
        values = newPtr;
        additionalCapacity = uint16_t( newCapacity - length );
    }
}
我明白这一点;它只是分配一个新数组,并将旧数组中的内存内容复制到新数组中,然后将旧数组的内容清零。我也知道这样做是为了防止调用析构函数和移动。
这JsonValue是一个带有函数的类,以及一些存储在联合中的数据(字符串、数组、数字等)。
我担心的是这是否实际上是定义的行为。我知道它有效,并且自从我们几个月前开始使用它以来一直没有问题;但如果它未定义,那么并不意味着它会继续工作。 …
std :: aligned_storage :: type是POD类型.POD类型可以memcpy.但是,如果将新的非平凡可复制类型放置到std :: aligned_storage会发生什么?它能记得那个std :: aligned_storage吗?
非平凡可复制类型(非POD类型)不能memcpy,行为未定义.如果std :: aligned_storage memcpy是非平凡可复制的类型,它是否也是未定义的行为?
#include <new>
#include <type_traits>
#include <cstring>
#include <iostream>
struct y { int a; } ;
// non-trivially-copyable
struct t
{
    y a;
    int* p;
    t(){ p = new int{ 300 }; }
    t( t const& ){ a.a += 100; }
    ~t(){ delete p; }
};
int main()
{   // Block 1
    { 
        t a; a.a.a = 100;
        t b; b.a.a = 200;
        // std::memcpy(&b,&a,sizeof(t));  // abort...non-trivially-copyable
    } …sizeof(double) char在寻找将s 组合到 a 的方法时double,我读了几篇文章,std::memcpy推荐使用以下方法:
char bytes[sizeof(double)];
// fill array
double d;
std::memcpy(&d, bytes, sizeof(double));
但是,我想知道为什么进一步使用d可以定义行为。
如果它不是一个double,而是一个复杂的类对象,那么访问它肯定也不会被定义,不是吗?那么,为什么double.
编辑:为了使我的问题清楚,我想指定我的目标:我想找到一种方法将多个chars 组合成 adouble并进一步使用这个 double,而不会导致未定义的行为。我不double希望指定 的值。无论如何,我认为这是不可能的,因为标准甚至没有说明任何有关大小的信息,更不用说double. 但是,我要求d有一些有效的(即“可访问的”)double值。
标准定义我们可以通过以下方式使用std :: memcpy:
对于任何简单的可复制类型T,如果指向T的两个指针指向不同的T对象obj1和obj2,其中obj1和obj2都不是基类子对象,如果构成obj1的基础字节(1.7)被复制到obj2中,obj2将随后保持与obj1相同的值.
如果我们将该函数应用于非平凡可复制类型的对象,我们可能会遇到什么样的潜在问题?以下代码的工作原理就好像它适用于普通可复制类型:
#include <iostream>
#include <cstring>
using std::cout;
using std::endl;
struct X
{
    int a = 6;
    X(){ }
    X(const X&)
    {
        cout << "X()" << endl;
    }
};
X a;
X b;
int main()
{
    a.a = 10;
    std::memcpy(&b, &a, sizeof(X));
    cout << b.a << endl; //10
}
我正在努力提供一组需要结构感知的序列化方法.因此,我构建了一个类模板,为从中继承的所有类提供这些方法.
这就是我现在所拥有的:
template<typename T>
class serializable
{
    protected:
        serializable() = default;
    public:
        size_t size_of() { return sizeof(T); }
        void   dump(void* data) { std::memcpy(data, this, serializable<T>::size_of()); }
        void   load(void* data) { std::memcpy(this, data, serializable<T>::size_of()); }
        virtual void serialize()
        {
            std::cout << "Default serialize : size " << serializable<T>::size_of() << std::endl;
        }
};
struct point : public serializable<point>
{
    float p[3];
};
struct particle : public point, public serializable<particle>
{
    float v[3];
};
int main()
{
    particle p;
    p.serialize();
    return 0;
} …c++ ×12
c ×2
c++11 ×2
memcpy ×2
arm ×1
c++14 ×1
implementation-defined-behavior ×1
inheritance ×1
lifetime ×1
neon ×1
templates ×1
type-traits ×1
types ×1
unique-ptr ×1
vector ×1