7

根据我的小测试,此代码有效。但是,它有未定义的行为吗?在我之前的测试中,通过使用 const_cast 修改 const 对象导致了运行时访问冲突,但我不记得它们有何不同。那么,这里是否存在根本性的问题?

// test.h
#pragma once
#include <boost/array.hpp>

typedef boost::array<int,100000> bigLut_t;
extern const bigLut_t constBigLut;

// test.cpp
#include "test.h"

bigLut_t& initializeConstBigLut()
{
    bigLut_t* pBigLut = const_cast<bigLut_t*>( &constBigLut );

    for(int i = 0; i < 100000; ++i) {
        pBigLut->at(i) = i;
    }
    return const_cast<bigLut_t&>(constBigLut);
}

const bigLut_t constBigLut = initializeConstBigLut();

// const_test.cpp
#include <iostream>
#include "test.h"

void main()
{
    for(int i = 0; i < 100; ++i) {
        std::cout << constBigLut[i] << std::endl;
    }
    system("pause");
}

(请注意 sizeof(bigLut_t) 太大而无法放入堆栈。)

编辑:我实际上最喜欢 ybungalobill 的小评论中的想法,最适合初始化这些大对象的方法:

// test.h
#pragma once
#include <boost/array.hpp>

extern const struct BigLut : public boost::array<int,100000> {
    BigLut();
} constBigLut;

// test.cpp
#include "test.h"

const BigLut constBigLut;
BigLut::BigLut()
{
    for(int i = 0; i < 100000; ++i) {
        this->at(i) = i;
    }
}
4

3 回答 3

6

您修改定义为 const 的对象。不管你什么时候做,在初始化期间与否,它仍然是未定义的行为。仅当 const 指针是在某个较早阶段从指向该对象的非 const 指针获得时,才定义使用 const_cast 删除 const 性。那不是你的情况。

你能做的最好的事情是

const bigLut_t& initializeConstBigLut()
{
    static bigLut_t bigLot;

    for(int i = 0; i < 100000; ++i) {
        bigLut.at(i) = i;
    }
    return bigLut;
}

const bigLut_t constBigLut = initializeConstBigLut();

并希望编译器将优化静态临时。

于 2010-11-27T11:44:35.577 回答
3

您正在滥用 const_cast 运算符,不幸的是,这是可能的,并且在这种情况下会生成未定义的行为...您可以constBigLut通过调用其隐式复制构造函数来使用动态初始化器(假设boost::array与 的概念相同std::array):

struct bigLut_tinit  {  
  bigLut_t BigLut; 

  bigLut_tinit() {
    for(int i = 0; i < 100000; ++i) {  
        BigLut[i] = i;  
    }
  }
};

const bigLut_tinit constBigLut;

编辑:似乎 VC++10 完美地应用了 RVO,以便将临时对象直接移动到静态持续时间对象中。所以恕我直言,无需声明本地静态变量或对临时变量的引用...

编辑2:是的,我错过了尺寸问题。建议使用上述构造函数包装成一个非平凡的类型......

于 2010-11-27T11:51:21.763 回答
1

它是一个 UB,因为该数组可以存储在 ROM 中。

你可以这样做:

// test.h
#include <boost/array.hpp>

typedef boost::array<int,100000> bigLut_t;
const bigLut_t& Lut();


// test.cpp
#include "test.h"

bool initialized=false;

const bigLut_t& Lut()
{
  static bigLut_t lut;

  if (!initialized)
  {
    for(int i = 0; i < 100000; ++i) {
        lut.at(i) = i;
    }
  }
    return lut;
}
于 2010-11-27T11:53:21.293 回答