在C++中进行'constify'操作是否有意义?

Fra*_*ank 6 c++ variables language-design syntactic-sugar

难道是有意义的有一个" constify"操作C/C++,使一个变量const

这是一个可能有用的示例,显然我们不想const在第一行声明它:

std::vector<int> v;
v.push_back(5);
constify v; // now it's const
Run Code Online (Sandbox Code Playgroud)

目前,没有这种可能性,你必须引入另一个变量来获得相同的效果:

std::vector<int> v0;
v0.push_back(5);
const std::vector<int>& v = v0;
Run Code Online (Sandbox Code Playgroud)

这更令人困惑,因为它在范围中添加了一个新名称,你需要使它成为一个参考,以避免复制整个向量(或使用swap?).

sbi*_*sbi 19

坦率地说,如果一个变量是否存在,我发现它变得不那么混乱了const.


详细说明一下:你通常想要这样做的原因是因为你无法const按照你想要的方式初始化变量.std::vector就是一个很好的例子.好吧,一次,下一个标准引入了一个通用的初始化语法,使这成为可能:

const std::vector<int> cvi = { 1, 2, 3, 4, 5, 42 }; 
Run Code Online (Sandbox Code Playgroud)

但是,即使没有C++ 1x的东西,即使是不允许这种初始化语法的类型,你总是可以创建一个帮助函数来做你想要的:

const std::vector<int>& cvi = create_my_vector();
Run Code Online (Sandbox Code Playgroud)

或者,如果你想要幻想:

const std::vector<int>& cvi = compile_time_list<1,2,3,4,5,42>::create_vector();
Run Code Online (Sandbox Code Playgroud)

Note the &. There's no point in copying the result of the function call, since binding an rvalue to a const reference extends its lifetime until the end of the reference's lifetime.
Of course, recompiling with a compiler that supports C++1x' move semantics will render such optimizations pretty much needless. But binding an rvlaue to a const reference might still be faster than moving a vector and is unlikely to be slower.
With C++1x, you might also create lambda functions doing this one the fly. C++ just provides an incredibly huge arsenal of tools. IME, no matter how hard you have thought, someone else ought to come up with yet another idea to do the same thing. And often a better one than yours.


但是,IME这个问题通常只会在功能太少的情况下带来太多的代码.然后它不仅适用于常数,也适用于类似的特征 - 就像参考文献所指的那样.
经典之作是使用多个可能的流中的一个.而不是这个

int main(int argc, char* argv[])
{
  std::istream* istrm = NULL;
  std::ifstream ifs;
  if( argc > 1 )
  {
    ifs.open( argv[1] );
    if( ifs.good() ) 
      istrm = &ifs;
  }
  if( !istrm ) 
    istrm = &std::cin;

  while( istrm->good() )
  {
     // reading from *istrm implemented here
  }
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

只是把问题分成1)找出从哪里读取和2)实际阅读:

int read(std::istream& is)
{
  while( is.good() )
  {
     // reading from is implemented here
  }
  return 0;
}

int main(int argc, char* argv[])
{
  if( argc > 1 )
  {
    std::ifstream ifs( argv[1] );
    if( ifs.good() ) 
      return read(ifs);
  }
  return read(std::cin);
}
Run Code Online (Sandbox Code Playgroud)

我还没有看到一个变量的真实世界的例子,这个变量并不像通过分离关注点那样无法解决.


Jer*_*fin 8

您基本上试图重现构造函数的效果 - 即,const仅在构造函数完成后才应用(并且仅在调用dtor之前应用).因此,你需要的是另一个包装你的矢量并在ctor中初始化它的类.一旦ctor完成并返回,实例就会变成const(当然,假定它被定义为const).

C++ 0x将大大改善这种包装的要求.您将能够使用大括号初始化器来在一次操作中创建/初始化向量.其他类型(至少可能)支持用户定义的初始化程序来完成大致相同的事情.


Ale*_*ler 7

C++是静态类型的.对我来说,引入这样的行动将违反这一范式,并会引起很多混乱.

  • @liori:也许吧.如果变量的类型在执行期间可能发生变化,这意味着我们需要执行执行路径分析来进行静态类型化.这并不适用于所有情况,并会在其他情况下产生令人惊讶的结果. (3认同)
  • 这仍然是静态类型 - 编译器可以在编译时推断变量是否为const. (2认同)

Bil*_*ill 6

这是使用功能的好时机

#include <vector>

std::vector<int> makeVector()
{
  std::vector<int> returnValue;
  returnValue.push_back(5);
  return returnValue;
}

int main()
{
  const std::vector<int> myVector = makeVector();
}
Run Code Online (Sandbox Code Playgroud)

  • @Jared:这个版本可能只创建一个向量(由于命名的返回值优化),你可以在一个范围内修改它然后在另一个范围内变得恒定,就像OP所希望的那样. (8认同)
  • @Jared:我把它读作:OP想要基本上创建一个常量向量,但不能由于缺少C++ 0x的初始化列表,或者没有同时拥有所有数据. (6认同)
  • 您的解决方案具有不同的语义.OP想要创建1`vector <T>`并更改标识符的const非const.您的解决方案创建了2个"vector <T>"副本,其中包含2个不同的访问权限 (2认同)